Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
HelpersMMPEVEM.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2002-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/****************************************************************************/
18// The MMP's emission model for electric vehicles.
19// If you use this model for academic research, you are highly encouraged to
20// cite our paper "Accurate physics-based modeling of electric vehicle energy
21// consumption in the SUMO traffic microsimulator"
22// (DOI: 10.1109/ITSC48978.2021.9564463).
23// Teaching and Research Area Mechatronics in Mobile Propulsion (MMP), RWTH Aachen
24/****************************************************************************/
25#include <config.h>
26
32
33
34// ===========================================================================
35// method definitions
36// ===========================================================================
72bool calcPowerConsumption(double m, double r_wheel, double Theta, double c_rr,
73 double c_d, double A_front, double i_gear, double eta_gear, double M_max,
74 double P_max, double M_recup_max, double P_recup_max, double R_battery,
75 double U_battery_0, double P_const,
76 const CharacteristicMap& ref_powerLossMap, double dt, double v, double a,
77 double alpha, double& ref_powerConsumption) {
78 const double EPS = 1e-6;
79 const double RHO_AIR = 1.204; // Air density [kg/m^3]
80 bool b_stateValid = true;
81
82 // Mass factor [1]
83 const double e_i = 1.0 + Theta / (m * r_wheel * r_wheel);
84 // Average speed during the previous timestep
85 const double v_mean = v - 0.5 * a * dt;
86
87 // Force required for the desired acceleration [N]
88 double F_a = m * a * e_i;
89 // Grade resistance [N]
90 double F_gr = m * GRAVITY * std::sin(DEG2RAD(alpha));
91 // Rolling resistance [N]
92 double F_rr = m * GRAVITY * std::cos(DEG2RAD(alpha)) * c_rr;
93 if (std::abs(v_mean) <= EPS) {
94 F_rr = 0;
95 }
96 // Drag [N]
97 double F_d = 0.5 * c_d * A_front * RHO_AIR * v_mean * v_mean;
98 // Tractive force [N]
99 const double F_tractive = F_a + F_gr + F_rr + F_d;
100
101 // Speed of the motor [rpm]
102 const double n_motor = v_mean / (2 * M_PI * r_wheel) * 60 * i_gear;
103 // Angular velocity of the motor [1/s]
104 double omega_motor = 2 * M_PI * n_motor / 60;
105 if (omega_motor == 0) {
106 omega_motor = EPS;
107 }
108
109 // Torque at the motor [Nm]. Please note that this model, like most real EVs,
110 // utilizes the EM to hold the vehicle on an incline rather than the brakes.
111 double M_motor = F_tractive * r_wheel / i_gear;
112 if (F_tractive < 0) {
113 M_motor *= eta_gear;
114 } else {
115 M_motor /= eta_gear;
116 }
117 // Engine power [W]
118 double P_motor = M_motor * omega_motor;
119
120 // Cap torque or power if necessary
121 // Accelerating
122 if (M_motor >= 0) {
123 if (M_motor > M_max) {
124 M_motor = M_max;
125 P_motor = M_motor * omega_motor;
126 b_stateValid = false;
127 }
128 if (P_motor > P_max) {
129 P_motor = P_max;
130 M_motor = P_motor / omega_motor;
131 b_stateValid = false;
132 }
133 }
134 // Recuperating
135 else {
136 // Even when capping, the state is still valid here because the extra energy
137 // is assumed to go to the brakes
138 if (M_motor < -M_recup_max) {
139 M_motor = -M_recup_max;
140 P_motor = M_motor * omega_motor;
141 }
142 if (P_motor < -P_recup_max) {
143 P_motor = -P_recup_max;
144 M_motor = P_motor / omega_motor;
145 }
146 }
147
148 // Power loss in the electric motor + inverter [W]
149 double P_loss_motor =
150 ref_powerLossMap.eval(std::vector<double> {n_motor, M_motor})[0];
151 if (std::isnan(P_loss_motor)) {
152 P_loss_motor = 0.0;
153 b_stateValid = false;
154 }
155
156 // Power demand at the battery [W]
157 double P_battery = P_motor + P_loss_motor + P_const;
158 // Total power demand (including the power loss in the battery) [W]
159 double P_total = (U_battery_0 * U_battery_0) / (2.0 * R_battery)
160 - U_battery_0 * std::sqrt((U_battery_0 * U_battery_0
161 - 4.0 * R_battery * P_battery) / (4.0 * R_battery * R_battery));
162
163 ref_powerConsumption = P_total;
164 return b_stateValid;
165}
166
167
172 : PollutantsInterface::Helper("MMPEVEM", MMPEVEM_BASE, MMPEVEM_BASE + 1)
173{ }
174
175
193 const PollutantsInterface::EmissionType e, const double v, const double a,
194 const double slope, const EnergyParams* ptr_energyParams) const {
195 if (e != PollutantsInterface::ELEC) {
196 return 0.0;
197 }
198
199 // Extract all required parameters, default values taken from the VW_ID3
200 // Vehicle mass [kg]
201 const double m = ptr_energyParams->getTotalMass(getWeight(c), 0.);
202 // Wheel radius [m]
203 const double r_wheel = ptr_energyParams->getDoubleOptional(SUMO_ATTR_WHEELRADIUS, 0.3588);
204 // Internal moment of inertia [kgm^2]
205 const double Theta = ptr_energyParams->getDoubleOptional(SUMO_ATTR_INTERNALMOMENTOFINERTIA, 12.5);
206 // Rolling resistance coefficient
207 const double c_rr = ptr_energyParams->getDoubleOptional(SUMO_ATTR_ROLLDRAGCOEFFICIENT, 0.007);
208 // Air drag coefficient
209 const double c_d = ptr_energyParams->getDoubleOptional(SUMO_ATTR_AIRDRAGCOEFFICIENT, 0.26);
210 // Cross-sectional area of the front of the car [m^2]
211 const double A_front = ptr_energyParams->getDoubleOptional(SUMO_ATTR_FRONTSURFACEAREA, 2.36);
212 // Gear ratio [1]
213 const double i_gear = ptr_energyParams->getDoubleOptional(SUMO_ATTR_GEARRATIO, 10.);
214 // Gearbox efficiency [1]
215 const double eta_gear = ptr_energyParams->getDoubleOptional(SUMO_ATTR_GEAREFFICIENCY, 0.96);
216 // Maximum torque [Nm]
217 const double M_max = ptr_energyParams->getDoubleOptional(SUMO_ATTR_MAXIMUMTORQUE, 310.);
218 // Maximum power [W]
219 const double P_max = ptr_energyParams->getDoubleOptional(SUMO_ATTR_MAXIMUMPOWER, 107000.);
220 // Maximum recuperation torque [Nm]
221 const double M_recup_max = ptr_energyParams->getDoubleOptional(SUMO_ATTR_MAXIMUMRECUPERATIONTORQUE, 95.5);
222 // Maximum recuperation power [W]
223 const double P_recup_max = ptr_energyParams->getDoubleOptional(SUMO_ATTR_MAXIMUMRECUPERATIONPOWER, 42800.);
224 // Internal battery resistance [Ohm]
225 const double R_battery = ptr_energyParams->getDoubleOptional(SUMO_ATTR_INTERNALBATTERYRESISTANCE, 0.1142);
226 // Nominal battery voltage [V]
227 const double U_battery_0 = ptr_energyParams->getDoubleOptional(SUMO_ATTR_NOMINALBATTERYVOLTAGE, 396.);
228 // Constant power consumption [W]
229 const double P_const = ptr_energyParams->getDoubleOptional(SUMO_ATTR_CONSTANTPOWERINTAKE, 360.);
230 // Power loss map
231 const CharacteristicMap& ref_powerLossMap = ptr_energyParams->getCharacteristicMap(SUMO_ATTR_POWERLOSSMAP);
232
233 double P = 0.0; // [W]
234 bool b_stateValid = calcPowerConsumption(m, r_wheel, Theta, c_rr, c_d,
235 A_front, i_gear, eta_gear, M_max, P_max, M_recup_max, P_recup_max,
236 R_battery, U_battery_0, P_const, ref_powerLossMap, TS, v, a, slope, P);
237 P /= 3600.0; // [Wh/s]
238
239 if (b_stateValid) {
240 return P;
241 } else {
242 return std::nan("");
243 }
244}
#define DEG2RAD(x)
Definition GeomHelper.h:35
#define GRAVITY
Definition GeomHelper.h:37
bool calcPowerConsumption(double m, double r_wheel, double Theta, double c_rr, double c_d, double A_front, double i_gear, double eta_gear, double M_max, double P_max, double M_recup_max, double P_recup_max, double R_battery, double U_battery_0, double P_const, const CharacteristicMap &ref_powerLossMap, double dt, double v, double a, double alpha, double &ref_powerConsumption)
Compute the power consumption of an EV powertrain in a certain state.
#define TS
Definition SUMOTime.h:42
int SUMOEmissionClass
@ SUMO_ATTR_GEAREFFICIENCY
Gear efficiency.
@ SUMO_ATTR_MAXIMUMPOWER
Maximum Power.
@ SUMO_ATTR_INTERNALBATTERYRESISTANCE
Internal battery resistance.
@ SUMO_ATTR_MAXIMUMTORQUE
Maximum torque.
@ SUMO_ATTR_ROLLDRAGCOEFFICIENT
Roll Drag coefficient.
@ SUMO_ATTR_CONSTANTPOWERINTAKE
Constant Power Intake.
@ SUMO_ATTR_WHEELRADIUS
@ SUMO_ATTR_AIRDRAGCOEFFICIENT
Air drag coefficient.
@ SUMO_ATTR_POWERLOSSMAP
A string encoding the power loss map.
@ SUMO_ATTR_MAXIMUMRECUPERATIONPOWER
Maximum recuperation power.
@ SUMO_ATTR_MAXIMUMRECUPERATIONTORQUE
Maximum recuperation torque.
@ SUMO_ATTR_GEARRATIO
Gear ratio.
@ SUMO_ATTR_INTERNALMOMENTOFINERTIA
Internal moment of inertia.
@ SUMO_ATTR_NOMINALBATTERYVOLTAGE
Nominal battery voltage.
@ SUMO_ATTR_FRONTSURFACEAREA
Front surface area.
The purpose of this class is to store a characteristic map (German: Kennfeld) of arbitrary dimensions...
std::vector< double > eval(const std::vector< double > &ref_p, double eps=1e-6) const
Evaluate a point in the map using linear interpolation.
An upper class for objects with additional parameters.
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...
const CharacteristicMap & getCharacteristicMap(SumoXMLAttr attr) const
Return the CharacteristicMap that belongs to a given attribute.
HelpersMMPEVEM()
Constructor.
double compute(const SUMOEmissionClass, const PollutantsInterface::EmissionType e, const double v, const double a, const double slope, const EnergyParams *ptr_energyParams) const
Compute the amount of emitted pollutants for an emission class in a given state.
double getWeight(const SUMOEmissionClass) const
Returns a reference weight in kg described by this emission class This implementation returns the def...
Helper methods for PHEMlight-based emission computation.
EmissionType
Enumerating all emission types, including fuel.
#define M_PI
Definition odrSpiral.cpp:45