Eclipse SUMO - Simulation of Urban MObility
HelpersPHEMlight.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2013-2022 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 /****************************************************************************/
20 // Helper methods for PHEMlight-based emission computation
21 /****************************************************************************/
22 #include <config.h>
23 
24 #include <limits>
25 #include <cmath>
26 #ifdef INTERNAL_PHEM
27 #include "PHEMCEPHandler.h"
28 #include "PHEMConstants.h"
29 #endif
33 
34 #include "HelpersPHEMlight.h"
35 
36 // idle speed is usually given in rpm (but may depend on electrical consumers). Actual speed depends on the gear so this number is only a rough estimate
37 #define IDLE_SPEED (10 / 3.6)
38 
39 // ===========================================================================
40 // method definitions
41 // ===========================================================================
43  PollutantsInterface::Helper("PHEMlight", PHEMLIGHT_BASE, -1),
44  myIndex(PHEMLIGHT_BASE) {
45 }
46 
47 
49 HelpersPHEMlight::getClassByName(const std::string& eClass, const SUMOVehicleClass vc) {
50  if (eClass == "unknown" && !myEmissionClassStrings.hasString("unknown")) {
51  myEmissionClassStrings.addAlias("unknown", getClassByName("PC_G_EU4", vc));
52  }
53  if (eClass == "default" && !myEmissionClassStrings.hasString("default")) {
54  myEmissionClassStrings.addAlias("default", getClassByName("PC_G_EU4", vc));
55  }
56  if (myEmissionClassStrings.hasString(eClass)) {
57  return myEmissionClassStrings.get(eClass);
58  }
59  if (eClass.size() < 6) {
60  throw InvalidArgument("Unknown emission class '" + eClass + "'.");
61  }
62  int index = myIndex++;
63  const std::string type = eClass.substr(0, 3);
64  if (type == "HDV" || type == "LB_" || type == "RB_" || type == "LSZ" || eClass.find("LKW") != std::string::npos) {
66  }
67  myEmissionClassStrings.insert(eClass, index);
68 #ifdef INTERNAL_PHEM
69  if (type == "HDV" || type == "LCV" || type == "PC_" || !PHEMCEPHandler::getHandlerInstance().Load(index, eClass)) {
70 #endif
71  std::vector<std::string> phemPath;
72  phemPath.push_back(OptionsCont::getOptions().getString("phemlight-path") + "/");
73  if (getenv("PHEMLIGHT_PATH") != nullptr) {
74  phemPath.push_back(std::string(getenv("PHEMLIGHT_PATH")) + "/");
75  }
76  if (getenv("SUMO_HOME") != nullptr) {
77  phemPath.push_back(std::string(getenv("SUMO_HOME")) + "/data/emissions/PHEMlight/");
78  }
80  myHelper.setPHEMDataV("V4");
81  myHelper.setclass(eClass);
82  if (!myCEPHandler.GetCEP(phemPath, &myHelper)) {
83  myEmissionClassStrings.remove(eClass, index);
84  myIndex--;
85  throw InvalidArgument("File for PHEM emission class " + eClass + " not found.\n" + myHelper.getErrMsg());
86  }
87  myCEPs[index] = myCEPHandler.getCEPS().find(myHelper.getgClass())->second;
88 #ifdef INTERNAL_PHEM
89  }
90 #endif
92  return index;
93 }
94 
95 
97 HelpersPHEMlight::getClass(const SUMOEmissionClass base, const std::string& vClass, const std::string& fuel, const std::string& eClass, const double weight) const {
98  std::string eClassOffset = "0";
99  if (eClass.length() == 5 && eClass.substr(0, 4) == "Euro") {
100  if (eClass[4] >= '0' && eClass[4] <= '6') {
101  eClassOffset = eClass.substr(4, 1);
102  }
103  }
104  std::string desc;
105  if (vClass == "Passenger") {
106  desc = "PKW_";
107  if (fuel == "Gasoline") {
108  desc += "G_";
109  } else if (fuel == "Diesel") {
110  desc += "D_";
111  } else if (fuel == "HybridGasoline") {
112  desc = "H_" + desc + "G_";
113  } else if (fuel == "HybridDiesel") {
114  desc = "H_" + desc + "G_";
115  }
116  desc += "EU" + eClassOffset;
117  } else if (vClass == "Moped") {
118  desc = "KKR_G_EU" + eClassOffset;
119  } else if (vClass == "Motorcycle") {
120  desc = "MR_G_EU" + eClassOffset;
121  if (fuel == "Gasoline2S") {
122  desc += "_2T";
123  } else {
124  desc += "_4T";
125  }
126  } else if (vClass == "Delivery") {
127  desc = "LNF_";
128  if (fuel == "Gasoline") {
129  desc += "G_";
130  } else if (fuel == "Diesel") {
131  desc += "D_";
132  }
133  desc += "EU" + eClassOffset + "_I";
134  if (weight > 1305.) {
135  desc += "I";
136  if (weight > 1760.) {
137  desc += "I";
138  }
139  }
140  } else if (vClass == "UrbanBus") {
141  desc = "LB_D_EU" + eClassOffset;
142  } else if (vClass == "Coach") {
143  desc = "RB_D_EU" + eClassOffset;
144  } else if (vClass == "Truck") {
145  desc = "Solo_LKW_D_EU" + eClassOffset + "_I";
146  if (weight > 1305.) {
147  desc += "I";
148  }
149  } else if (vClass == "Trailer") {
150  desc = "LSZ_D_EU" + eClassOffset;
151  }
152  if (myEmissionClassStrings.hasString(desc)) {
153  return myEmissionClassStrings.get(desc);
154  }
155  return base;
156 }
157 
158 
159 std::string
161  const std::string name = myEmissionClassStrings.getString(c);
162  if (name.find("KKR_") != std::string::npos) {
163  return "Moped";
164  } else if (name.find("RB_") != std::string::npos) {
165  return "Coach";
166  } else if (name.find("LB_") != std::string::npos) {
167  return "UrbanBus";
168  } else if (name.find("LNF_") != std::string::npos) {
169  return "Delivery";
170  } else if (name.find("LSZ_") != std::string::npos) {
171  return "Trailer";
172  } else if (name.find("MR_") != std::string::npos) {
173  return "Motorcycle";
174  } else if (name.find("LKW_") != std::string::npos) {
175  return "Truck";
176  }
177  return "Passenger";
178 }
179 
180 
181 std::string
183  const std::string name = myEmissionClassStrings.getString(c);
184  std::string fuel = "Gasoline";
185  if (name.find("_D_") != std::string::npos) {
186  fuel = "Diesel";
187  }
188  if (name.find("H_") != std::string::npos) {
189  fuel = "Hybrid" + fuel;
190  }
191  return fuel;
192 }
193 
194 
195 int
197  const std::string name = myEmissionClassStrings.getString(c);
198  if (name.find("_EU1") != std::string::npos) {
199  return 1;
200  } else if (name.find("_EU2") != std::string::npos) {
201  return 2;
202  } else if (name.find("_EU3") != std::string::npos) {
203  return 3;
204  } else if (name.find("_EU4") != std::string::npos) {
205  return 4;
206  } else if (name.find("_EU5") != std::string::npos) {
207  return 5;
208  } else if (name.find("_EU6") != std::string::npos) {
209  return 6;
210  }
211  return 0;
212 }
213 
214 
215 double
217  const std::string name = myEmissionClassStrings.getString(c);
218  if (name.find("LNF_") != std::string::npos) {
219  if (name.find("_III") != std::string::npos) {
220  return 2630.;
221  } else if (name.find("_II") != std::string::npos) {
222  return 1532.;
223  } else if (name.find("_I") != std::string::npos) {
224  return 652.;
225  }
226  }
227  if (name.find("Solo_LKW_") != std::string::npos) {
228  if (name.find("_II") != std::string::npos) {
229  return 8398.;
230  } else if (name.find("_I") != std::string::npos) {
231  return 18702.;
232  }
233  }
234  return -1.;
235 }
236 
237 
238 double
239 HelpersPHEMlight::getEmission(const PHEMCEP* oldCep, PHEMlightdll::CEP* currCep, const std::string& e, const double p, const double v) const {
240  if (oldCep != nullptr) {
241  return oldCep->GetEmission(e, p, v);
242  }
243  return currCep->GetEmission(e, p, v, &myHelper);
244 }
245 
246 
247 double
248 HelpersPHEMlight::getModifiedAccel(const SUMOEmissionClass c, const double v, const double a, const double slope) const {
249  PHEMlightdll::CEP* currCep = myCEPs.count(c) == 0 ? 0 : myCEPs.find(c)->second;
250  if (currCep != nullptr) {
251  return v == 0.0 ? 0.0 : MIN2(a, currCep->GetMaxAccel(v, slope));
252  }
253  return a;
254 }
255 
256 
257 double
258 HelpersPHEMlight::compute(const SUMOEmissionClass c, const PollutantsInterface::EmissionType e, const double v, const double a, const double slope, const EnergyParams* /* param */) const {
259  const double corrSpeed = MAX2(0.0, v);
260  double power = 0.;
261 #ifdef INTERNAL_PHEM
262  const PHEMCEP* const oldCep = PHEMCEPHandler::getHandlerInstance().GetCep(c);
263  if (oldCep != nullptr) {
264  if (v > IDLE_SPEED && a < oldCep->GetDecelCoast(corrSpeed, a, slope, 0)) {
265  // coasting without power use only works if the engine runs above idle speed and
266  // the vehicle does not accelerate beyond friction losses
267  return 0;
268  }
269  power = oldCep->CalcPower(corrSpeed, a, slope);
270  }
271 #else
272  const PHEMCEP* const oldCep = 0;
273 #endif
274  PHEMlightdll::CEP* currCep = myCEPs.count(c) == 0 ? 0 : myCEPs.find(c)->second;
275  if (currCep != nullptr) {
276  const double corrAcc = getModifiedAccel(c, corrSpeed, a, slope);
277  if (currCep->getFuelType() != PHEMlightdll::Constants::strBEV &&
278  corrAcc < currCep->GetDecelCoast(corrSpeed, corrAcc, slope) &&
280  // the IDLE_SPEED fix above is now directly in the decel coast calculation.
281  return 0;
282  }
283  power = currCep->CalcPower(corrSpeed, corrAcc, slope);
284  }
285  const std::string& fuelType = oldCep != nullptr ? oldCep->GetVehicleFuelType() : currCep->getFuelType();
286  switch (e) {
288  return getEmission(oldCep, currCep, "CO", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
290  if (oldCep != nullptr) {
291  return getEmission(oldCep, currCep, "FC", power, corrSpeed) * 3.15 / SECONDS_PER_HOUR * 1000.;
292  }
293  return currCep->GetCO2Emission(getEmission(nullptr, currCep, "FC", power, corrSpeed),
294  getEmission(nullptr, currCep, "CO", power, corrSpeed),
295  getEmission(nullptr, currCep, "HC", power, corrSpeed), &myHelper) / SECONDS_PER_HOUR * 1000.;
297  return getEmission(oldCep, currCep, "HC", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
299  return getEmission(oldCep, currCep, "NOx", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
301  return getEmission(oldCep, currCep, "PM", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
303  if (fuelType == PHEMlightdll::Constants::strDiesel) { // divide by average diesel density of 836 g/l
304  return getEmission(oldCep, currCep, "FC", power, corrSpeed) / 836. / SECONDS_PER_HOUR * 1000.;
305  } else if (fuelType == PHEMlightdll::Constants::strGasoline) { // divide by average gasoline density of 742 g/l
306  return getEmission(oldCep, currCep, "FC", power, corrSpeed) / 742. / SECONDS_PER_HOUR * 1000.;
307  } else if (fuelType == PHEMlightdll::Constants::strBEV) {
308  return 0;
309  } else {
310  return getEmission(oldCep, currCep, "FC", power, corrSpeed) / SECONDS_PER_HOUR * 1000.; // surely false, but at least not additionally modified
311  }
312  }
314  if (fuelType == PHEMlightdll::Constants::strBEV) {
315  return getEmission(oldCep, currCep, "FC", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
316  }
317  return 0;
318  }
319  // should never get here
320  return 0.;
321 }
322 
323 
324 /****************************************************************************/
#define IDLE_SPEED
const double SECONDS_PER_HOUR
Definition: PHEMConstants.h:27
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
int SUMOEmissionClass
T MIN2(T a, T b)
Definition: StdDefs.h:74
T MAX2(T a, T b)
Definition: StdDefs.h:80
An upper class for objects with additional parameters.
Definition: EnergyParams.h:41
double getEmission(const PHEMCEP *oldCep, PHEMlightdll::CEP *currCep, const std::string &e, const double p, const double v) const
Returns the amount of emitted pollutant given the vehicle type and state (in mg/s or in ml/s for fuel...
std::map< SUMOEmissionClass, PHEMlightdll::CEP * > myCEPs
SUMOEmissionClass getClass(const SUMOEmissionClass base, const std::string &vClass, const std::string &fuel, const std::string &eClass, const double weight) const
Returns the emission class described by the given parameters.
std::string getFuel(const SUMOEmissionClass c) const
Returns the fuel type described by this emission class as described in the Amitran interface (Gasolin...
PHEMlightdll::Helpers myHelper
double compute(const SUMOEmissionClass c, const PollutantsInterface::EmissionType e, const double v, const double a, const double slope, const EnergyParams *param) const
Returns the amount of emitted pollutant given the vehicle type and state (in mg/s or in ml/s for fuel...
HelpersPHEMlight()
Constructor.
double getModifiedAccel(const SUMOEmissionClass c, const double v, const double a, const double slope) const
Returns the adapted acceleration value, useful for comparing with external PHEMlight references.
int getEuroClass(const SUMOEmissionClass c) const
Returns the Euro emission class described by this emission class as described in the Amitran interfac...
SUMOEmissionClass getClassByName(const std::string &eClass, const SUMOVehicleClass vc)
Checks whether the string describes a known vehicle class.
double getWeight(const SUMOEmissionClass c) const
Returns a reference weight in kg described by this emission class as described in the Amitran interfa...
PHEMlightdll::CEPHandler myCEPHandler
int myIndex
the index of the next class
std::string getAmitranVehicleClass(const SUMOEmissionClass c) const
Returns the vehicle class described by this emission class as described in the Amitran interface (Pas...
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
static PHEMCEPHandler & getHandlerInstance()
Implementatio of Singelton pattern.
PHEMCEP * GetCep(SUMOEmissionClass emissionClass)
Returns the CEP data for a PHEM emission class.
Data Handler for a single CEP emission data set.
Definition: PHEMCEP.h:50
double CalcPower(double v, double a, double slope, double vehicleLoading=0) const
Returns the power of used for a vehicle at state v,a, slope and loading.
Definition: PHEMCEP.cpp:399
double GetEmission(const std::string &pollutantIdentifier, double power, double speed, bool normalized=false) const
Returns a emission measure for power[kW] level.
Definition: PHEMCEP.cpp:196
const std::string & GetVehicleFuelType() const
Getter function to recieve vehicle data from CEP.
Definition: PHEMCEP.h:221
const std::map< std::string, CEP * > & getCEPS() const
Definition: CEPHandler.cpp:39
bool GetCEP(const std::vector< std::string > &DataPath, Helpers *Helper)
Definition: CEPHandler.cpp:43
double GetMaxAccel(double speed, double gradient)
Definition: CEP.cpp:420
double GetEmission(const std::string &pollutant, double power, double speed, Helpers *VehicleClass)
Definition: CEP.cpp:230
double CalcPower(double speed, double acc, double gradient)
Definition: CEP.cpp:200
const std::string & getFuelType() const
Definition: CEP.cpp:172
double GetCO2Emission(double _FC, double _CO, double _HC, Helpers *VehicleClass)
Definition: CEP.cpp:291
static const std::string strGasoline
Definition: Constants.h:58
static const double ZERO_SPEED_ACCURACY
Definition: Constants.h:39
static const std::string strBEV
Definition: Constants.h:63
static const std::string strDiesel
Definition: Constants.h:59
const std::string & getErrMsg() const
Definition: Helpers.cpp:71
void setPHEMDataV(const std::string &value)
Definition: Helpers.cpp:91
void setCommentPrefix(const std::string &value)
Definition: Helpers.cpp:83
const std::string & getgClass() const
Definition: Helpers.cpp:63
bool setclass(const std::string &VEH)
Definition: Helpers.cpp:241
StringBijection< SUMOEmissionClass > myEmissionClassStrings
Mapping between emission class names and integer representations.
Helper methods for PHEMlight-based emission computation.
EmissionType
Enumerating all emission types, including fuel.
static const int HEAVY_BIT
the bit to set for denoting heavy vehicles
void remove(const std::string str, const T key)
bool hasString(const std::string &str) const
const std::string & getString(const T key) const
void addAlias(const std::string str, const T key)
T get(const std::string &str) const
void insert(const std::string str, const T key, bool checkDuplicates=true)
static std::string to_lower_case(std::string str)
Transfers the content to lower case.
Definition: StringUtils.cpp:59