Eclipse SUMO - Simulation of Urban MObility
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
HelpersEnergy.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// Helper methods for HBEFA-based emission computation
22/****************************************************************************/
23#include <config.h>
24
25#include <complex> // due to sqrt of complex
26#include <utils/common/MsgHandler.h> // due to WRITE_WARNING
30#include "HelpersEnergy.h"
31
32
33// ===========================================================================
34// method definitions
35// ===========================================================================
37 PollutantsInterface::Helper("Energy", ENERGY_BASE, ENERGY_BASE)
38{ }
39
40
41double
42HelpersEnergy::compute(const SUMOEmissionClass /* c */, const PollutantsInterface::EmissionType e, const double v, const double a, const double slope, const EnergyParams* param) const {
44 return 0.;
45 }
46 if (param == nullptr) {
48 }
49 if (param->isOff()) {
50 return 0.;
51 }
52 //@ToDo: All formulas below work with the logic of the euler update (refs #860).
53 // Approximation order could be improved. Refs. #2592.
54
55 const double lastV = v - ACCEL2SPEED(a);
56 const double mass = param->getTotalMass(myDefaultMass, 0.);
57
58 // calculate power needed for potential energy difference
59 double power = mass * GRAVITY * sin(DEG2RAD(slope)) * v;
60
61 // power needed for kinetic energy difference of vehicle
62 power += 0.5 * mass * (v * v - lastV * lastV) / TS;
63
64 // add power needed for rotational energy diff of internal rotating elements
65 power += 0.5 * param->getDoubleOptional(SUMO_ATTR_ROTATINGMASS, myDefaultRotatingMass) * (v * v - lastV * lastV) / TS;
66
67 // power needed for Energy loss through Air resistance [Ws]
68 // Calculate energy losses:
69 // EnergyLoss,Air = 1/2 * rho_air [kg/m^3] * myFrontSurfaceArea [m^2] * myAirDragCoefficient [-] * v_Veh^2 [m/s] * s [m]
70 // ... with rho_air [kg/m^3] = 1,2041 kg/m^3 (at T = 20C)
71 // ... with s [m] = v_Veh [m/s] * TS [s]
72 // divided by TS to get power instead of energy
74
75 // power needed for Energy loss through Roll resistance [Ws]
76 // ... (fabs(veh.getSpeed())>=0.01) = 0, if vehicle isn't moving
77 // EnergyLoss,Tire = c_R [-] * F_N [N] * s [m]
78 // ... with c_R = ~0.012 (car tire on asphalt)
79 // ... with F_N [N] = myMass [kg] * g [m/s^2]
80 // divided by TS to get power instead of energy
82
83 // Energy loss through friction by radial force [Ws]
84 // If angle of vehicle was changed
85 const double angleDiff = param->getAngleDiff();
86 if (angleDiff != 0.) {
87 // Compute new radio
88 double radius = SPEED2DIST(v) / fabs(angleDiff);
89
90 // Check if radius is in the interval [0.0001 - 10000] (To avoid overflow and division by zero)
91 if (radius < 0.0001) {
92 radius = 0.0001;
93 } else if (radius > 10000) {
94 radius = 10000;
95 }
96 // EnergyLoss,internalFrictionRadialForce = c [m] * F_rad [N];
97 // Energy loss through friction by radial force [Ws]
98 // divided by TS to get power instead of energy
100 }
101
102 // E_Bat = E_kin_pot + EnergyLoss;
103 if (power > 0) {
104 // Assumption: Efficiency of myPropulsionEfficiency when accelerating
106 } else {
107 // Assumption: Efficiency of myRecuperationEfficiency when recuperating
109 if (a != 0) {
110 // Fiori, Chiara & Ahn, Kyoungho & Rakha, Hesham. (2016).
111 // Power-based electric vehicle energy consumption model: Model
112 // development and validation. Applied Energy. 168. 257-268.
113 // 10.1016/j.apenergy.2016.01.097.
114 //
115 // Insaf Sagaama, Amine Kchiche, Wassim Trojet, Farouk Kamoun
116 // Improving The Accuracy of The Energy Consumption Model for
117 // Electric Vehicle in SUMO Considering The Ambient Temperature
118 // Effects
120 }
121 }
122
123 // EnergyLoss,constantConsumers
124 // Energy loss through constant loads (e.g. A/C) [W]
126
127 // convert from [W], to [Wh/s] (3600s / 1h):
128 return power / 3600.;
129}
130
131
132double
133HelpersEnergy::acceleration(const SUMOEmissionClass /* c */, const PollutantsInterface::EmissionType e, const double v, const double P, const double slope, const EnergyParams* param) const {
134 if (e != PollutantsInterface::ELEC) {
135 return 0.;
136 }
137
138 if (param == nullptr) {
139 param = EnergyParams::getDefault();
140 }
141
142 // Inverse formula for the function compute()
143
144 // Computes the achievable acceleration using the given speed and drive power in [Wh/s]
145 // It does not consider friction losses by radial force and the acceleration-dependent
146 // recuperation efficiency (eta_recuperation is considered constant)
147 //
148 // The power `Prest` used for acceleration is given by a cubic polynomial in acceleration,
149 // i.e.the equation
150 //
151 // Prest = const1*a + const2*a^2 + const3*a^3
152 //
153 // and we need to find `a` given `Prest`.
154 //
155 // The solutions of `a(P)` is stored in variables `x1`, `x2`, and `x3` returned by
156 // the method `PolySolver::cubicSolve()`, see below.
157 //
158 // Power used for accelerating, `Prest`, is the total used power minus power wasted by running resistances.
159
160 const double mass = param->getTotalMass(myDefaultMass, 0.);
161 const double rotMass = param->getDoubleOptional(SUMO_ATTR_ROTATINGMASS, myDefaultRotatingMass);
162 double const1, const2, const3;
163 double Prest;
164 int numX;
165 double x1, x2, x3;
166
167 // Power delivered by the drive
168 if (P > 0) {
169 // Assumption: Efficiency of myPropulsionEfficiency when accelerating
171 } else {
172 // Assumption: Efficiency of myRecuperationEfficiency when recuperating
174 }
175
176 // calculate power drop due to a potential energy difference
177 // in inverse original formula: power = mass * GRAVITY * sin(DEG2RAD(slope)) * v;
178 // i.e. in terms of 'lastV' and 'a': power = mass * GRAVITY * sin(DEG2RAD(slope)) * (lastV + TS * a);
179 Prest -= mass * GRAVITY * sin(DEG2RAD(slope)) * (v);
180 const1 = mass * GRAVITY * sin(DEG2RAD(slope)) * (TS);
181
182 // update coefficients of a(P) equation considering power loss through Roll resistance
183 // in inverse original formula: power += param->getDoubleOptional(SUMO_ATTR_ROLLDRAGCOEFFICIENT) * GRAVITY * mass * v;
184 // i.e. in terms of 'lastV' and 'a': power += param->getDoubleOptional(SUMO_ATTR_ROLLDRAGCOEFFICIENT) * GRAVITY * mass * (lastV + TS * a);
187
188 //Constant loads are omitted. We assume P as the max limit for the main traction drive. Constant loads are often covered by an auxiliary drive
189 //Power loss through constant loads (e.g. A/C) [W]
190 //Prest -= param->getDoubleOptional(SUMO_ATTR_CONSTANTPOWERINTAKE) / TS;
191
192 // update coefficients of a(P) equation considering kinetic energy difference of vehicle
193 // in inverse original formula: power += 0.5 * mass * (v * v - lastV * lastV) / TS;
194 // i.e. in terms of 'lastV' and 'a': power += 0.5 * mass * (2 * lastV * a + TS * a * a);
195 const1 += 0.5 * mass * (2 * v);
196 const2 = 0.5 * mass * (TS);
197
198 // update coefficients of a(P) equation considering rotational energy diff of internal rotating elements
199 // in inverse original formula: power += 0.5 * rotMass * (v * v - lastV * lastV) / TS;
200 // i.e. in terms of 'lastV' and 'a': power += 0.5 * rotMass * (2 * lastV * a + TS * a * a);
201 const1 += 0.5 * rotMass * (2 * v);
202 const2 += 0.5 * rotMass * (TS);
203
204 // update coefficients of a(P) equation considering energy loss through Air resistance
205 // in inverse original formula: power += 0.5 * 1.2041 * param->getDoubleOptional(SUMO_ATTR_FRONTSURFACEAREA) * param->getDoubleOptional(SUMO_ATTR_AIRDRAGCOEFFICIENT) * v * v * v;
206 // i.e. in terms of 'lastV' and 'a': power += 0.5 * rotMass * (lastV^3 + 3* lastV^2 * TS * a + 3* lastV * TS^2 *a^2 + TS^3 * a^3);
208 Prest -= drag * (v * v * v);
209 const1 += drag * (3 * v * v * TS);
210 const2 += drag * (3 * v * TS * TS);
211 const3 = drag * (TS * TS * TS);
212
213 // Prest = const1*a + const2*a^2 + const3*a^3
214 // Solve cubic equation in `a` for real roots, and return the number of roots in `numX`
215 // and the roots in `x1`, `x2`, and `x3`.
216 std::tie(numX, x1, x2, x3) = PolySolver::cubicSolve(const3, const2, const1, -Prest);
217
218
219 switch (numX) {
220 case 1:
221 return x1;
222 case 2:
223 return MAX2(x1, x2);
224 case 3:
225 return MAX3(x1, x2, x3);
226 default:
227 WRITE_ERROR(TL("An acceleration given by the power was not found."));
228 return 0;
229 }
230
231}
232
233
234/****************************************************************************/
#define DEG2RAD(x)
Definition GeomHelper.h:35
#define GRAVITY
Definition GeomHelper.h:37
#define WRITE_ERROR(msg)
Definition MsgHandler.h:296
#define TL(string)
Definition MsgHandler.h:305
#define SPEED2DIST(x)
Definition SUMOTime.h:45
#define ACCEL2SPEED(x)
Definition SUMOTime.h:51
#define TS
Definition SUMOTime.h:42
int SUMOEmissionClass
@ SUMO_ATTR_ROLLDRAGCOEFFICIENT
Roll Drag coefficient.
@ SUMO_ATTR_CONSTANTPOWERINTAKE
Constant Power Intake.
@ SUMO_ATTR_RECUPERATIONEFFICIENCY_BY_DECELERATION
Recuperation efficiency (by deceleration)
@ SUMO_ATTR_RECUPERATIONEFFICIENCY
Recuperation efficiency (constant)
@ SUMO_ATTR_AIRDRAGCOEFFICIENT
Air drag coefficient.
@ SUMO_ATTR_RADIALDRAGCOEFFICIENT
Radial drag coefficient.
@ SUMO_ATTR_ROTATINGMASS
Mass equivalent of rotating elements.
@ SUMO_ATTR_PROPULSIONEFFICIENCY
Propulsion efficiency.
@ SUMO_ATTR_FRONTSURFACEAREA
Front surface area.
T MAX2(T a, T b)
Definition StdDefs.h:82
T MAX3(T a, T b, T c)
Definition StdDefs.h:96
An upper class for objects with additional parameters.
bool isOff() const
Returns whether the vehicle is currently consuming any energy derived from the parking state.
double getTotalMass(const double defaultEmptyMass, const double defaultLoading) const
Returns the sum of the empty mass (SUMO_ATTR_MASS), tthe loading (SUMO_ATTR_LOADING) and the mass of ...
double getDoubleOptional(SumoXMLAttr attr, const double def) const
Returns the value for a given key with an optional default. SUMO_ATTR_MASS and SUMO_ATTR_FRONTSURFACE...
static const EnergyParams * getDefault()
double getAngleDiff() const
Returns the angle difference between the last two calls of setDynamicValues (usually the last two tim...
static constexpr double myDefaultRadialDragCoefficient
double compute(const SUMOEmissionClass c, const PollutantsInterface::EmissionType e, const double v, const double a, const double slope, const EnergyParams *param) const
Computes the emitted pollutant amount using the given speed and acceleration.
static constexpr double myDefaultFrontSurfaceArea
static constexpr double myDefaultRollDragCoefficient
double acceleration(const SUMOEmissionClass c, const PollutantsInterface::EmissionType e, const double v, const double P, const double slope, const EnergyParams *param) const
Computes the achievable acceleration using the given speed and amount of consumed electric power.
static constexpr double myDefaultRecuperationEfficiency
HelpersEnergy()
Constructor (initializes myEmissionClassStrings)
static constexpr double myDefaultMass
static constexpr double myDefaultRotatingMass
static constexpr double myDefaultRecuperationEfficiencyByDeceleration
static constexpr double myDefaultAirDragCoefficient
static constexpr double myDefaultConstantPowerIntake
static constexpr double myDefaultPropulsionEfficiency
Helper methods for PHEMlight-based emission computation.
EmissionType
Enumerating all emission types, including fuel.
static std::tuple< int, double, double, double > cubicSolve(double a, double b, double c, double d)
Solver of cubic equation ax^3 + bx^2 + cx + d = 0.