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-2020 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
32 #include "HelpersPHEMlight.h"
33 
34 // 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
35 #define IDLE_SPEED (10 / 3.6)
36 
37 // ===========================================================================
38 // method definitions
39 // ===========================================================================
40 HelpersPHEMlight::HelpersPHEMlight() : PollutantsInterface::Helper("PHEMlight"), myIndex(PHEMLIGHT_BASE) {
41 }
42 
43 
45 HelpersPHEMlight::getClassByName(const std::string& eClass, const SUMOVehicleClass vc) {
46  if (eClass == "unknown" && !myEmissionClassStrings.hasString("unknown")) {
47  myEmissionClassStrings.addAlias("unknown", getClassByName("PC_G_EU4", vc));
48  }
49  if (eClass == "default" && !myEmissionClassStrings.hasString("default")) {
50  myEmissionClassStrings.addAlias("default", getClassByName("PC_G_EU4", vc));
51  }
52  if (myEmissionClassStrings.hasString(eClass)) {
53  return myEmissionClassStrings.get(eClass);
54  }
55  if (eClass.size() < 6) {
56  throw InvalidArgument("Unknown emission class '" + eClass + "'.");
57  }
58  int index = myIndex++;
59  const std::string type = eClass.substr(0, 3);
60  if (type == "HDV" || type == "LB_" || type == "RB_" || type == "LSZ" || eClass.find("LKW") != std::string::npos) {
62  }
63  myEmissionClassStrings.insert(eClass, index);
64 #ifdef INTERNAL_PHEM
65  if (type == "HDV" || type == "LCV" || type == "PC_" || !PHEMCEPHandler::getHandlerInstance().Load(index, eClass)) {
66 #endif
67  std::vector<std::string> phemPath;
68  phemPath.push_back(OptionsCont::getOptions().getString("phemlight-path") + "/");
69  if (getenv("PHEMLIGHT_PATH") != nullptr) {
70  phemPath.push_back(std::string(getenv("PHEMLIGHT_PATH")) + "/");
71  }
72  if (getenv("SUMO_HOME") != nullptr) {
73  phemPath.push_back(std::string(getenv("SUMO_HOME")) + "/data/emissions/PHEMlight/");
74  }
76  myHelper.setPHEMDataV("V4");
77  myHelper.setclass(eClass);
78  if (!myCEPHandler.GetCEP(phemPath, &myHelper)) {
79  myEmissionClassStrings.remove(eClass, index);
80  myIndex--;
81  throw InvalidArgument("File for PHEM emission class " + eClass + " not found.\n" + myHelper.getErrMsg());
82  }
83  myCEPs[index] = myCEPHandler.getCEPS().find(myHelper.getgClass())->second;
84 #ifdef INTERNAL_PHEM
85  }
86 #endif
87  std::string eclower = eClass;
88  std::transform(eclower.begin(), eclower.end(), eclower.begin(), tolower);
89  myEmissionClassStrings.addAlias(eclower, index);
90  return index;
91 }
92 
93 
95 HelpersPHEMlight::getClass(const SUMOEmissionClass base, const std::string& vClass, const std::string& fuel, const std::string& eClass, const double weight) const {
96  std::string eClassOffset = "0";
97  if (eClass.length() == 5 && eClass.substr(0, 4) == "Euro") {
98  if (eClass[4] >= '0' && eClass[4] <= '6') {
99  eClassOffset = eClass.substr(4, 1);
100  }
101  }
102  std::string desc;
103  if (vClass == "Passenger") {
104  desc = "PKW_";
105  if (fuel == "Gasoline") {
106  desc += "G_";
107  } else if (fuel == "Diesel") {
108  desc += "D_";
109  } else if (fuel == "HybridGasoline") {
110  desc = "H_" + desc + "G_";
111  } else if (fuel == "HybridDiesel") {
112  desc = "H_" + desc + "G_";
113  }
114  desc += "EU" + eClassOffset;
115  } else if (vClass == "Moped") {
116  desc = "KKR_G_EU" + eClassOffset;
117  } else if (vClass == "Motorcycle") {
118  desc = "MR_G_EU" + eClassOffset;
119  if (fuel == "Gasoline2S") {
120  desc += "_2T";
121  } else {
122  desc += "_4T";
123  }
124  } else if (vClass == "Delivery") {
125  desc = "LNF_";
126  if (fuel == "Gasoline") {
127  desc += "G_";
128  } else if (fuel == "Diesel") {
129  desc += "D_";
130  }
131  desc += "EU" + eClassOffset + "_I";
132  if (weight > 1305.) {
133  desc += "I";
134  if (weight > 1760.) {
135  desc += "I";
136  }
137  }
138  } else if (vClass == "UrbanBus") {
139  desc = "LB_D_EU" + eClassOffset;
140  } else if (vClass == "Coach") {
141  desc = "RB_D_EU" + eClassOffset;
142  } else if (vClass == "Truck") {
143  desc = "Solo_LKW_D_EU" + eClassOffset + "_I";
144  if (weight > 1305.) {
145  desc += "I";
146  }
147  } else if (vClass == "Trailer") {
148  desc = "LSZ_D_EU" + eClassOffset;
149  }
150  if (myEmissionClassStrings.hasString(desc)) {
151  return myEmissionClassStrings.get(desc);
152  }
153  return base;
154 }
155 
156 
157 std::string
159  const std::string name = myEmissionClassStrings.getString(c);
160  if (name.find("KKR_") != std::string::npos) {
161  return "Moped";
162  } else if (name.find("RB_") != std::string::npos) {
163  return "Coach";
164  } else if (name.find("LB_") != std::string::npos) {
165  return "UrbanBus";
166  } else if (name.find("LNF_") != std::string::npos) {
167  return "Delivery";
168  } else if (name.find("LSZ_") != std::string::npos) {
169  return "Trailer";
170  } else if (name.find("MR_") != std::string::npos) {
171  return "Motorcycle";
172  } else if (name.find("LKW_") != std::string::npos) {
173  return "Truck";
174  }
175  return "Passenger";
176 }
177 
178 
179 std::string
181  const std::string name = myEmissionClassStrings.getString(c);
182  std::string fuel = "Gasoline";
183  if (name.find("_D_") != std::string::npos) {
184  fuel = "Diesel";
185  }
186  if (name.find("H_") != std::string::npos) {
187  fuel = "Hybrid" + fuel;
188  }
189  return fuel;
190 }
191 
192 
193 int
195  const std::string name = myEmissionClassStrings.getString(c);
196  if (name.find("_EU1") != std::string::npos) {
197  return 1;
198  } else if (name.find("_EU2") != std::string::npos) {
199  return 2;
200  } else if (name.find("_EU3") != std::string::npos) {
201  return 3;
202  } else if (name.find("_EU4") != std::string::npos) {
203  return 4;
204  } else if (name.find("_EU5") != std::string::npos) {
205  return 5;
206  } else if (name.find("_EU6") != std::string::npos) {
207  return 6;
208  }
209  return 0;
210 }
211 
212 
213 double
215  const std::string name = myEmissionClassStrings.getString(c);
216  if (name.find("LNF_") != std::string::npos) {
217  if (name.find("_III") != std::string::npos) {
218  return 2630.;
219  } else if (name.find("_II") != std::string::npos) {
220  return 1532.;
221  } else if (name.find("_I") != std::string::npos) {
222  return 652.;
223  }
224  }
225  if (name.find("Solo_LKW_") != std::string::npos) {
226  if (name.find("_II") != std::string::npos) {
227  return 8398.;
228  } else if (name.find("_I") != std::string::npos) {
229  return 18702.;
230  }
231  }
232  return -1.;
233 }
234 
235 
236 double
237 HelpersPHEMlight::getEmission(const PHEMCEP* oldCep, PHEMlightdll::CEP* currCep, const std::string& e, const double p, const double v) const {
238  if (oldCep != nullptr) {
239  return oldCep->GetEmission(e, p, v);
240  }
241  return currCep->GetEmission(e, p, v, &myHelper);
242 }
243 
244 
245 double
246 HelpersPHEMlight::getModifiedAccel(const SUMOEmissionClass c, const double v, const double a, const double slope) const {
247  PHEMlightdll::CEP* currCep = myCEPs.count(c) == 0 ? 0 : myCEPs.find(c)->second;
248  if (currCep != nullptr) {
249  return v == 0.0 ? 0.0 : MIN2(a, currCep->GetMaxAccel(v, slope));
250  }
251  return a;
252 }
253 
254 
255 double
256 HelpersPHEMlight::compute(const SUMOEmissionClass c, const PollutantsInterface::EmissionType e, const double v, const double a, const double slope, const std::map<int, double>* /* param */) const {
257  const double corrSpeed = MAX2(0.0, v);
258  double power = 0.;
259 #ifdef INTERNAL_PHEM
260  const PHEMCEP* const oldCep = PHEMCEPHandler::getHandlerInstance().GetCep(c);
261  if (oldCep != nullptr) {
262  if (v > IDLE_SPEED && a < oldCep->GetDecelCoast(corrSpeed, a, slope, 0)) {
263  // coasting without power use only works if the engine runs above idle speed and
264  // the vehicle does not accelerate beyond friction losses
265  return 0;
266  }
267  power = oldCep->CalcPower(corrSpeed, a, slope);
268  }
269 #else
270  const PHEMCEP* const oldCep = 0;
271 #endif
272  PHEMlightdll::CEP* currCep = myCEPs.count(c) == 0 ? 0 : myCEPs.find(c)->second;
273  if (currCep != nullptr) {
274  const double corrAcc = getModifiedAccel(c, corrSpeed, a, slope);
275  if (currCep->getFuelType() != PHEMlightdll::Constants::strBEV &&
276  corrAcc < currCep->GetDecelCoast(corrSpeed, corrAcc, slope) &&
278  // the IDLE_SPEED fix above is now directly in the decel coast calculation.
279  return 0;
280  }
281  power = currCep->CalcPower(corrSpeed, corrAcc, slope);
282  }
283  const std::string& fuelType = oldCep != nullptr ? oldCep->GetVehicleFuelType() : currCep->getFuelType();
284  switch (e) {
286  return getEmission(oldCep, currCep, "CO", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
288  if (oldCep != nullptr) {
289  return getEmission(oldCep, currCep, "FC", power, corrSpeed) * 3.15 / SECONDS_PER_HOUR * 1000.;
290  }
291  return currCep->GetCO2Emission(getEmission(nullptr, currCep, "FC", power, corrSpeed),
292  getEmission(nullptr, currCep, "CO", power, corrSpeed),
293  getEmission(nullptr, currCep, "HC", power, corrSpeed), &myHelper) / SECONDS_PER_HOUR * 1000.;
295  return getEmission(oldCep, currCep, "HC", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
297  return getEmission(oldCep, currCep, "NOx", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
299  return getEmission(oldCep, currCep, "PM", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
301  if (fuelType == PHEMlightdll::Constants::strDiesel) { // divide by average diesel density of 836 g/l
302  return getEmission(oldCep, currCep, "FC", power, corrSpeed) / 836. / SECONDS_PER_HOUR * 1000.;
303  } else if (fuelType == PHEMlightdll::Constants::strGasoline) { // divide by average gasoline density of 742 g/l
304  return getEmission(oldCep, currCep, "FC", power, corrSpeed) / 742. / SECONDS_PER_HOUR * 1000.;
305  } else if (fuelType == PHEMlightdll::Constants::strBEV) {
306  return 0;
307  } else {
308  return getEmission(oldCep, currCep, "FC", power, corrSpeed) / SECONDS_PER_HOUR * 1000.; // surely false, but at least not additionally modified
309  }
310  }
312  if (fuelType == PHEMlightdll::Constants::strBEV) {
313  return getEmission(oldCep, currCep, "FC", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
314  }
315  return 0;
316  }
317  // should never get here
318  return 0.;
319 }
320 
321 
322 /****************************************************************************/
#define IDLE_SPEED
const double SECONDS_PER_HOUR
Definition: PHEMConstants.h:26
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:73
T MAX2(T a, T b)
Definition: StdDefs.h:79
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 std::map< int, double > *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:61
static const double ZERO_SPEED_ACCURACY
Definition: Constants.h:41
static const std::string strBEV
Definition: Constants.h:66
static const std::string strDiesel
Definition: Constants.h:62
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)