Eclipse SUMO - Simulation of Urban MObility
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-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 /****************************************************************************/
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 
27 #include <utils/common/SUMOTime.h>
29 #include <utils/geom/GeomHelper.h>
32 
33 
34 // ===========================================================================
35 // method definitions
36 // ===========================================================================
72 bool 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 
168 
169 
174  : PollutantsInterface::Helper("MMPEVEM", MMPEVEM_BASE, MMPEVEM_BASE + 1)
175 { }
176 
177 
178 
179 
180 
198  const PollutantsInterface::EmissionType e, const double v, const double a,
199  const double slope, const EnergyParams* ptr_energyParams) const {
200  if (e != PollutantsInterface::ELEC) {
201  return 0.0;
202  }
203 
204  // Extract all required parameters
205  // Vehicle mass
206  const double m = ptr_energyParams->getDouble(SUMO_ATTR_MASS) + ptr_energyParams->getDoubleOptional(SUMO_ATTR_LOADING, 0.);
207  // Wheel radius
208  const double r_wheel = ptr_energyParams->getDouble(SUMO_ATTR_WHEELRADIUS);
209  // Internal moment of inertia
210  const double Theta
211  = ptr_energyParams->getDouble(SUMO_ATTR_INTERNALMOMENTOFINERTIA);
212  // Rolling resistance coefficient
213  const double c_rr
214  = ptr_energyParams->getDouble(SUMO_ATTR_ROLLDRAGCOEFFICIENT);
215  // Air drag coefficient
216  const double c_d = ptr_energyParams->getDouble(SUMO_ATTR_AIRDRAGCOEFFICIENT);
217  // Cross-sectional area of the front of the car
218  const double A_front
219  = ptr_energyParams->getDouble(SUMO_ATTR_FRONTSURFACEAREA);
220  // Gear ratio
221  const double i_gear = ptr_energyParams->getDouble(SUMO_ATTR_GEARRATIO);
222  // Gearbox efficiency
223  const double eta_gear = ptr_energyParams->getDouble(SUMO_ATTR_GEAREFFICIENCY);
224  // Maximum torque
225  const double M_max = ptr_energyParams->getDouble(SUMO_ATTR_MAXIMUMTORQUE);
226  // Maximum power
227  const double P_max = ptr_energyParams->getDouble(SUMO_ATTR_MAXIMUMPOWER);
228  // Maximum recuperation torque
229  const double M_recup_max
230  = ptr_energyParams->getDouble(SUMO_ATTR_MAXIMUMRECUPERATIONTORQUE);
231  // Maximum recuperation power
232  const double P_recup_max
233  = ptr_energyParams->getDouble(SUMO_ATTR_MAXIMUMRECUPERATIONPOWER);
234  // Internal battery resistance
235  const double R_battery
236  = ptr_energyParams->getDouble(SUMO_ATTR_INTERNALBATTERYRESISTANCE);
237  // Nominal battery voltage
238  const double U_battery_0
239  = ptr_energyParams->getDouble(SUMO_ATTR_NOMINALBATTERYVOLTAGE);
240  // Constant power consumption
241  const double P_const
242  = ptr_energyParams->getDouble(SUMO_ATTR_CONSTANTPOWERINTAKE);
243  // Power loss map
244  const CharacteristicMap& ref_powerLossMap
245  = ptr_energyParams->getCharacteristicMap(SUMO_ATTR_POWERLOSSMAP);
246 
247  double P = 0.0; // [W]
248  bool b_stateValid = calcPowerConsumption(m, r_wheel, Theta, c_rr, c_d,
249  A_front, i_gear, eta_gear, M_max, P_max, M_recup_max, P_recup_max,
250  R_battery, U_battery_0, P_const, ref_powerLossMap, TS, v, a, slope, P);
251  P /= 3600.0; // [Wh/s]
252 
253  if (b_stateValid) {
254  return P;
255  } else {
256  return std::nan("");
257  }
258 }
#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_MASS
@ SUMO_ATTR_ROLLDRAGCOEFFICIENT
Roll Drag coefficient.
@ SUMO_ATTR_CONSTANTPOWERINTAKE
Constant Power Intake.
@ SUMO_ATTR_LOADING
additional mass loaded on the vehicle
@ 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.
Definition: EnergyParams.h:43
double getDouble(SumoXMLAttr attr) const
double getDoubleOptional(SumoXMLAttr attr, const double def) const
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.
Helper methods for PHEMlight-based emission computation.
EmissionType
Enumerating all emission types, including fuel.
#define M_PI
Definition: odrSpiral.cpp:45