Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MSChargingStation.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-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/****************************************************************************/
21// Charging Station for Electric vehicles
22/****************************************************************************/
23#include <config.h>
24
25#include <cassert>
34#include <microsim/MSNet.h>
35#include "MSChargingStation.h"
36
37
38// ===========================================================================
39// member method definitions
40// ===========================================================================
41
42MSChargingStation::MSChargingStation(const std::string& chargingStationID, MSLane& lane, double startPos, double endPos,
43 const std::string& name, double chargingPower, double totalPower, double efficency, bool chargeInTransit,
44 SUMOTime chargeDelay, const std::string& chargeType, SUMOTime waitingTime) :
45 MSStoppingPlace(chargingStationID, SUMO_TAG_CHARGING_STATION, std::vector<std::string>(), lane, startPos, endPos, name),
46 myChargeInTransit(chargeInTransit), myChargeType(stringToChargeType(chargeType)), myTotalPowerCheckEvent(nullptr) {
47 if (chargingPower < 0) {
48 WRITE_WARNING(TLF("Attribute % for chargingStation with ID='%' is invalid (%).", toString(SUMO_ATTR_CHARGINGPOWER), getID(), toString(chargingPower)))
49 } else {
50 myNominalChargingPower = chargingPower;
51 myTotalChargingPower = totalPower;
52 }
53 if (efficency < 0 || efficency > 1) {
54 WRITE_WARNING(TLF("Attribute % for chargingStation with ID='%' is invalid (%).", toString(SUMO_ATTR_EFFICIENCY), getID(), toString(efficency)))
55 } else {
56 myEfficiency = efficency;
57 }
58 if (chargeDelay < 0) {
59 WRITE_WARNING(TLF("Attribute % for chargingStation with ID='%' is invalid (%).", toString(SUMO_ATTR_CHARGEDELAY), getID(), toString(chargeDelay)))
60 } else {
61 myChargeDelay = chargeDelay;
62 }
63 if (waitingTime < 0) {
64 WRITE_WARNING(TLF("Attribute % for chargingStation with ID='%' is invalid (%).", toString(SUMO_ATTR_WAITINGTIME), getID(), toString(waitingTime)))
65 } else {
66 myWaitingTime = waitingTime;
67 }
69 WRITE_WARNING(TLF("ChargingStation with ID='%' doesn't have a valid position (% < %).", getID(), toString(getBeginLanePosition()), toString(getEndLanePosition())));
70 }
71}
72
73
74MSChargingStation::MSChargingStation(const std::string& chargingStationID, const MSParkingArea* parkingArea, const std::string& name, double chargingPower,
75 double totalPower, double efficency, bool chargeInTransit, SUMOTime chargeDelay, const std::string& chargeType, SUMOTime waitingTime) :
76 MSChargingStation(chargingStationID, const_cast<MSLane&>(parkingArea->getLane()), parkingArea->getBeginLanePosition(), parkingArea->getEndLanePosition(),
77 name, chargingPower, totalPower, efficency, chargeInTransit, chargeDelay, chargeType, waitingTime) {
78 myParkingArea = parkingArea;
79}
80
81
84
85
86double
88 if (usingFuel) {
90 } else {
91 // Convert from [Ws] to [Wh] (3600s / 1h):
92 return myNominalChargingPower / 3600;
93 }
94}
95
96
97double
101
102
103bool
107
108
113
114
119
120
125
126
127const MSParkingArea*
131
132
133void
135 myNominalChargingPower = chargingPower;
136}
137
138
139void
141 myEfficiency = efficiency;
142}
143
144
145void
149
150
151void
159
160
161void
169
170
174 myTotalPowerCheckEvent = nullptr;
175 myChargedBatteries.clear();
176 return 0;
177 }
178 double sumReqWh = 0;
179 std::vector<Charge*> thisStepCharges;
180 for (auto& kv : myChargeValues) {
181 if (MSNet::getInstance()->getVehicleControl().getVehicle(kv.first) == nullptr) {
182 continue;
183 }
184 Charge& lastcharge = kv.second.back();
185 if (lastcharge.timeStep == currentTime) {
186 sumReqWh += lastcharge.WCharged;
187 thisStepCharges.push_back(&lastcharge);
188 }
189 }
190 if (thisStepCharges.size() < 2) {
191 return DELTA_T;
192 }
193 const double capWh = myTotalChargingPower * myEfficiency /*W*/ * TS /*s*/ / 3600.0; // convert to Wh
194#ifdef DEBUG_SIMSTEP
195 std::cout << "checkTotalPower: CS="
196 << this->myID << " currentTime=" << currentTime << " myTotalChargingPower=" << myTotalChargingPower;
197 if (sumReqWh > capWh && sumReqWh > 0)
198 std::cout << " exceeded, needs rebalancing!";
199 std::cout << std::endl;
200#endif
201 if (sumReqWh > capWh && sumReqWh > 0) {
202 const double ratio = capWh / sumReqWh;
203 for (auto* charge : thisStepCharges) {
204 const double deliveredWh = charge->WCharged * ratio;
205 const double excessWh = charge->WCharged - deliveredWh;
206 charge->WCharged = deliveredWh;
207
208 // inform also battery device
209 MSDevice_Battery* battery = myChargedBatteries[charge->vehicleID];
210 double abc = battery->getActualBatteryCapacity();
211 battery->setActualBatteryCapacity(abc - excessWh);
212 battery->setEnergyCharged(deliveredWh);
213 }
214 }
215 return DELTA_T;
216}
217
218
219bool
220MSChargingStation::vehicleIsInside(const double position) const {
221 if ((position >= getBeginLanePosition()) && (position <= getEndLanePosition())) {
222 return true;
223 } else {
224 return false;
225 }
226}
227
228
229bool
233
234
235void
237 if (!OptionsCont::getOptions().isSet("chargingstations-output")) {
238 return;
239 }
240 std::string status = "";
241 if (battery->getChargingStartTime() > myChargeDelay) {
242 if (battery->getHolder().getSpeed() < battery->getStoppingThreshold()) {
243 status = "chargingStopped";
244 } else if (myChargeInTransit) {
245 status = "chargingInTransit";
246 } else {
247 status = "noCharging";
248 }
249 } else {
250 if (myChargeInTransit) {
251 status = "waitingChargeInTransit";
252 } else if (battery->getHolder().getSpeed() < battery->getStoppingThreshold()) {
253 status = "waitingChargeStopped";
254 } else {
255 status = "noWaitingCharge";
256 }
257 }
258 // update total charge
259 myTotalCharge += WCharged;
260 // create charge row and insert it in myChargeValues
261 const std::string vehID = battery->getHolder().getID();
262 if (myChargeValues.count(vehID) == 0) {
263 myChargedVehicles.push_back(vehID);
264 myChargedBatteries[vehID] = battery;
265 }
266 Charge C(MSNet::getInstance()->getCurrentTimeStep(), vehID, battery->getHolder().getVehicleType().getID(),
267 status, WCharged, battery->getActualBatteryCapacity(), battery->getMaximumBatteryCapacity(),
269 myChargeValues[vehID].push_back(C);
270}
271
272
273void
275 int chargingSteps = 0;
276 for (const auto& item : myChargeValues) {
277 chargingSteps += (int)item.second.size();
278 }
280 output.writeAttr(SUMO_ATTR_ID, myID);
282 output.writeAttr(SUMO_ATTR_CHARGINGSTEPS, chargingSteps);
283 // start writing
284 if (myChargeValues.size() > 0) {
285 for (const std::string& vehID : myChargedVehicles) {
286 int iStart = 0;
287 const auto& chargeSteps = myChargeValues[vehID];
288 while (iStart < (int)chargeSteps.size()) {
289 int iEnd = iStart + 1;
290 double charged = chargeSteps[iStart].WCharged;
291 while (iEnd < (int)chargeSteps.size() && chargeSteps[iEnd].timeStep == chargeSteps[iEnd - 1].timeStep + DELTA_T) {
292 charged += chargeSteps[iEnd].WCharged;
293 iEnd++;
294 }
295 writeVehicle(output, chargeSteps, iStart, iEnd, charged);
296 iStart = iEnd;
297 }
298 }
299 }
300 // close charging station tag
301 output.closeTag();
302}
303
304
305void
307 std::vector<std::string> terminatedChargers;
308 for (const auto& item : myChargeValues) {
309 const Charge& lastCharge = item.second.back();
310 // no charge during the last time step == has stopped charging
311 bool finished = lastCharge.timeStep < SIMSTEP - DELTA_T;
312 if (finished || includeUnfinished) {
313 if (finished) {
314 terminatedChargers.push_back(item.first);
315 }
316 // aggregate values
317 double charged = 0.;
318 double minPower = lastCharge.chargingPower;
319 double maxPower = lastCharge.chargingPower;
320 double minCharge = lastCharge.WCharged;
321 double maxCharge = lastCharge.WCharged;
322 double minEfficiency = lastCharge.chargingEfficiency;
323 double maxEfficiency = lastCharge.chargingEfficiency;
324 for (const auto& charge : item.second) {
325 charged += charge.WCharged;
326 if (charge.chargingPower < minPower) {
327 minPower = charge.chargingPower;
328 }
329 if (charge.chargingPower > maxPower) {
330 maxPower = charge.chargingPower;
331 }
332 if (charge.WCharged < minCharge) {
333 minCharge = charge.WCharged;
334 }
335 if (charge.WCharged > maxCharge) {
336 maxCharge = charge.WCharged;
337 }
338 if (charge.chargingEfficiency < minEfficiency) {
339 minEfficiency = charge.chargingEfficiency;
340 }
341 if (charge.chargingEfficiency > maxEfficiency) {
342 maxEfficiency = charge.chargingEfficiency;
343 }
344 }
345 // actually write the data
348 output.writeAttr(SUMO_ATTR_VEHICLE, lastCharge.vehicleID);
349 output.writeAttr(SUMO_ATTR_TYPE, lastCharge.vehicleType);
351 output.writeAttr(SUMO_ATTR_CHARGINGBEGIN, time2string(item.second.at(0).timeStep));
352 if (finished) {
354 }
357 output.writeAttr(SUMO_ATTR_MINPOWER, minPower);
358 output.writeAttr(SUMO_ATTR_MAXPOWER, maxPower);
359 output.writeAttr(SUMO_ATTR_MINCHARGE, minCharge);
360 output.writeAttr(SUMO_ATTR_MAXCHARGE, maxCharge);
361 output.writeAttr(SUMO_ATTR_MINEFFICIENCY, minEfficiency);
362 output.writeAttr(SUMO_ATTR_MAXEFFICIENCY, maxEfficiency);
363 output.closeTag();
364 }
365 }
366
367 // clear charging data of vehicles which terminated charging
368 for (auto vehID : terminatedChargers) {
369 myChargeValues.erase(vehID);
370 }
371}
372
373
374void
375MSChargingStation::writeVehicle(OutputDevice& out, const std::vector<Charge>& chargeSteps, int iStart, int iEnd, double charged) {
376 const Charge& first = chargeSteps[iStart];
378 out.writeAttr(SUMO_ATTR_ID, first.vehicleID);
382 out.writeAttr(SUMO_ATTR_CHARGINGEND, time2string(chargeSteps[iEnd - 1].timeStep));
383 for (int i = iStart; i < iEnd; i++) {
384 const Charge& c = chargeSteps[i];
387 // charge values
391 // charging values of charging station in this timestep
394 // battery status of vehicle
397 // close tag timestep
398 out.closeTag();
399 }
400 out.closeTag();
401}
402
403
404/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define WRITE_WARNING(msg)
Definition MsgHandler.h:286
#define TLF(string,...)
Definition MsgHandler.h:306
SUMOTime DELTA_T
Definition SUMOTime.cpp:38
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition SUMOTime.cpp:91
#define SIMSTEP
Definition SUMOTime.h:61
#define TS
Definition SUMOTime.h:42
@ SUMO_TAG_CHARGING_STATION
A Charging Station.
@ SUMO_TAG_CHARGING_EVENT
A charging event (charging a vehicle at a charging station)
@ SUMO_TAG_STEP
trigger: a step description
@ SUMO_TAG_VEHICLE
description of a vehicle
@ SUMO_ATTR_PARTIALCHARGE
energy provided by charging station at certain timestep
@ SUMO_ATTR_TOTALENERGYCHARGED
@ SUMO_ATTR_MINPOWER
minimum charging power encountered during the charging event
@ SUMO_ATTR_WAITINGTIME
@ SUMO_ATTR_MAXIMUMBATTERYCAPACITY
Maxium battery capacity.
@ SUMO_ATTR_MINEFFICIENCY
minimum charging efficiency encountered during the charging event
@ SUMO_ATTR_MAXCHARGE
maximum energy charged during one time step of the charging event
@ SUMO_ATTR_MAXPOWER
@ SUMO_ATTR_TOTALENERGYCHARGED_VEHICLE
total energy charged into a single vehicle
@ SUMO_ATTR_CHARGINGSTATIONID
Charging Station ID.
@ SUMO_ATTR_ACTUALBATTERYCAPACITY
@ SUMO_ATTR_ENERGYCHARGED
tgotal of Energy charged
@ SUMO_ATTR_CHARGINGPOWER
@ SUMO_ATTR_MAXEFFICIENCY
maximum charging efficiency encountered during the charging event
@ SUMO_ATTR_VEHICLE
@ SUMO_ATTR_TYPE
@ SUMO_ATTR_CHARGINGSTEPS
number of steps that a vehicle is charging
@ SUMO_ATTR_CHARGINGEND
timesteps in which charging ends
@ SUMO_ATTR_EFFICIENCY
Eficiency of the charge in Charging Stations.
@ SUMO_ATTR_CHARGINGBEGIN
timestep in which charging begins
@ SUMO_ATTR_ID
@ SUMO_ATTR_MINCHARGE
minimum energy charged during one time step of the charging event
@ SUMO_ATTR_CHARGEDELAY
Delay in the charge of charging stations (different of waiting time)
@ SUMO_ATTR_TIME
trigger: the time of the step
@ SUMO_ATTR_CHARGING_STATUS
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
void setChargeInTransit(bool value)
set charging in transit
void writeChargingStationOutput(OutputDevice &output)
write charging station values
double myTotalCharge
total energy charged by this charging station
static void writeVehicle(OutputDevice &out, const std::vector< Charge > &chargeSteps, int iStart, int iEnd, double charged)
std::map< std::string, MSDevice_Battery * > myChargedBatteries
map with the Batteries charged by this charging station (key = vehicleID)
double getChargingPower(bool usingFuel) const
Get charging station's charging power.
const ChargeType myChargeType
charge type
bool getChargeInTransit() const
Get chargeInTransit.
void setChargingVehicle(bool value)
enable or disable charging vehicle
std::vector< std::string > myChargedVehicles
order vehicles by time of first charge
MSChargingStation(const std::string &chargingStationID, MSLane &lane, double startPos, double endPos, const std::string &name, double chargingPower, double totalPower, double efficency, bool chargeInTransit, SUMOTime chargeDelay, const std::string &chargeType, SUMOTime waitingTime)
constructor
double myEfficiency
Efficiency of the charging station.
void setEfficiency(double efficiency)
set efficiency of the charging station
void setChargingPower(double chargingPower)
set charging station's charging power
Command * myTotalPowerCheckEvent
Event for checking at every time-step if myTotalPower has been exceeded.
double myTotalChargingPower
The maximal charging power available to serve all charging vehicles (value <= 0 take no effect)
SUMOTime myWaitingTime
waiting time
double myNominalChargingPower
Charging station's nominal charging power per vehicle.
bool myChargeInTransit
Allow charge in transit.
bool vehicleIsInside(const double position) const
Check if a vehicle is inside in the Charge Station.
const MSParkingArea * myParkingArea
parkingArea the charging station is placed on
std::map< std::string, std::vector< Charge > > myChargeValues
map with the charges of this charging station (key = vehicleID)
void addChargeValueForOutput(double WCharged, MSDevice_Battery *battery)
add charge value for output
SUMOTime getChargeDelay() const
Get Charge Delay.
void writeAggregatedChargingStationOutput(OutputDevice &output, bool includeUnfinished=false)
write ungrouped output (flush data after writing)
void setChargeDelay(SUMOTime delay)
set charging delay of the charging station
double getEfficency() const
Get efficiency of the charging station.
ChargeType getChargeType() const
Get charge type.
SUMOTime myChargeDelay
Charge Delay.
~MSChargingStation()
destructor
bool myChargingVehicle
Check if in the current TimeStep chargingStation is charging a vehicle.
bool isCharging() const
Return true if in the current time step charging station is charging a vehicle.
SUMOTime getWaitingTime() const
Get waiting time.
SUMOTime checkTotalPower(SUMOTime currentTime)
update the delivered power to all charging vehicles after all requests are known
const MSParkingArea * getParkingArea() const
Get the parking area the charging station is placed on.
Battery device for electric vehicles.
void setEnergyCharged(const double energyCharged)
Set Energy Charged in Wh.
SUMOTime getChargingStartTime() const
Get charging start time.
double getActualBatteryCapacity() const
Get the actual vehicle's Battery Capacity in Wh.
double getMaximumBatteryCapacity() const
Get the total vehicle's Battery Capacity in Wh.
void setActualBatteryCapacity(const double actualBatteryCapacity)
Set actual vehicle's Battery Capacity in kWh.
double getStoppingThreshold() const
Get stopping threshold.
virtual void addEvent(Command *operation, SUMOTime execTimeStep=-1)
Adds an Event.
Representation of a lane in the micro simulation.
Definition MSLane.h:84
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:187
MSEventControl * getEndOfTimestepEvents()
Returns the event control for events executed at the end of a time step.
Definition MSNet.h:495
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition MSNet.h:392
A lane area vehicles can halt at.
A lane area vehicles can halt at.
double getBeginLanePosition() const
Returns the begin position of this stop.
double getEndLanePosition() const
Returns the end position of this stop.
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
SUMOVehicle & getHolder() const
Returns the vehicle that holds this device.
const std::string & getID() const
Returns the name of the vehicle type.
std::string myID
The name of the object.
Definition Named.h:125
const std::string & getID() const
Returns the id.
Definition Named.h:74
static OptionsCont & getOptions()
Retrieves the options.
Static storage of an output device and its base (abstract) implementation.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
virtual const MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
virtual double getSpeed() const =0
Returns the object's current speed.
A wrapper for a Command function.
Definition json.hpp:4471
struct to save information for the chargingStation output