SUMO - Simulation of Urban MObility
HelpersPHEMlight.cpp
Go to the documentation of this file.
1 /****************************************************************************/
9 // Helper methods for PHEMlight-based emission computation
10 /****************************************************************************/
11 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
12 // Copyright (C) 2013-2017 DLR (http://www.dlr.de/) and contributors
13 /****************************************************************************/
14 //
15 // This file is part of SUMO.
16 // SUMO is free software: you can redistribute it and/or modify
17 // it under the terms of the GNU General Public License as published by
18 // the Free Software Foundation, either version 3 of the License, or
19 // (at your option) any later version.
20 //
21 /****************************************************************************/
22 
23 
24 // ===========================================================================
25 // included modules
26 // ===========================================================================
27 #ifdef _MSC_VER
28 #include <windows_config.h>
29 #else
30 #include <config.h>
31 #endif
32 
33 #include <limits>
34 #include <cmath>
35 #ifdef INTERNAL_PHEM
36 #include "PHEMCEPHandler.h"
37 #include "PHEMConstants.h"
38 #endif
40 #include "HelpersPHEMlight.h"
41 
42 // 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
43 #define IDLE_SPEED (10 / 3.6)
44 
45 // ===========================================================================
46 // method definitions
47 // ===========================================================================
48 HelpersPHEMlight::HelpersPHEMlight() : PollutantsInterface::Helper("PHEMlight"), myIndex(PHEMLIGHT_BASE) {
50 }
51 
52 
54 HelpersPHEMlight::getClassByName(const std::string& eClass, const SUMOVehicleClass vc) {
55  if (eClass == "unknown" && !myEmissionClassStrings.hasString("unknown")) {
56  myEmissionClassStrings.addAlias("unknown", getClassByName("PKW_G_EU4", vc));
57  }
58  if (myEmissionClassStrings.hasString(eClass)) {
59  return myEmissionClassStrings.get(eClass);
60  }
61  if (eClass.size() < 6) {
62  throw InvalidArgument("Unknown emission class '" + eClass + "'.");
63  }
64  int index = myIndex++;
65  const std::string type = eClass.substr(0, 3);
66  if (type == "HDV" || type == "LB_" || type == "RB_" || type == "LSZ" || eClass.find("LKW") != std::string::npos) {
68  }
69  myEmissionClassStrings.insert(eClass, index);
70 #ifdef INTERNAL_PHEM
71  if (type == "HDV" || type == "LCV" || type == "PC_" || !PHEMCEPHandler::getHandlerInstance().Load(index, eClass)) {
72 #endif
73  std::vector<std::string> phemPath;
74  phemPath.push_back(OptionsCont::getOptions().getString("phemlight-path") + "/");
75  if (getenv("PHEMLIGHT_PATH") != 0) {
76  phemPath.push_back(std::string(getenv("PHEMLIGHT_PATH")) + "/");
77  }
78  if (getenv("SUMO_HOME") != 0) {
79  phemPath.push_back(std::string(getenv("SUMO_HOME")) + "/data/emissions/PHEMlight/");
80  }
82  myHelper.setPHEMDataV("V4");
83  myHelper.setclass(eClass);
84  if (!myCEPHandler.GetCEP(phemPath, &myHelper)) {
85  myEmissionClassStrings.remove(eClass, index);
86  myIndex--;
87  throw InvalidArgument("File for PHEM emission class " + eClass + " not found.\n" + myHelper.getErrMsg());
88  }
89  myCEPs[index] = myCEPHandler.getCEPS().find(myHelper.getgClass())->second;
90 #ifdef INTERNAL_PHEM
91  }
92 #endif
93  std::string eclower = eClass;
94  std::transform(eclower.begin(), eclower.end(), eclower.begin(), tolower);
95  myEmissionClassStrings.addAlias(eclower, index);
96  return index;
97 }
98 
99 
101 HelpersPHEMlight::getClass(const SUMOEmissionClass base, const std::string& vClass, const std::string& fuel, const std::string& eClass, const double weight) const {
102  std::string eClassOffset = "0";
103  if (eClass.length() == 5 && eClass.substr(0, 4) == "Euro") {
104  if (eClass[4] >= '0' && eClass[4] <= '6') {
105  eClassOffset = eClass.substr(4, 1);
106  }
107  }
108  std::string desc;
109  if (vClass == "Passenger") {
110  desc = "PKW_";
111  if (fuel == "Gasoline") {
112  desc += "G_";
113  } else if (fuel == "Diesel") {
114  desc += "D_";
115  } else if (fuel == "HybridGasoline") {
116  desc = "H_" + desc + "G_";
117  } else if (fuel == "HybridDiesel") {
118  desc = "H_" + desc + "G_";
119  }
120  desc += "EU" + eClassOffset;
121  } else if (vClass == "Moped") {
122  desc = "KKR_G_EU" + eClassOffset;
123  } else if (vClass == "Motorcycle") {
124  desc = "MR_G_EU" + eClassOffset;
125  if (fuel == "Gasoline2S") {
126  desc += "_2T";
127  } else {
128  desc += "_4T";
129  }
130  } else if (vClass == "Delivery") {
131  desc = "LNF_";
132  if (fuel == "Gasoline") {
133  desc += "G_";
134  } else if (fuel == "Diesel") {
135  desc += "D_";
136  }
137  desc += "EU" + eClassOffset + "_I";
138  if (weight > 1305.) {
139  desc += "I";
140  if (weight > 1760.) {
141  desc += "I";
142  }
143  }
144  } else if (vClass == "UrbanBus") {
145  desc = "LB_D_EU" + eClassOffset;
146  } else if (vClass == "Coach") {
147  desc = "RB_D_EU" + eClassOffset;
148  } else if (vClass == "Truck") {
149  desc = "Solo_LKW_D_EU" + eClassOffset + "_I";
150  if (weight > 1305.) {
151  desc += "I";
152  }
153  } else if (vClass == "Trailer") {
154  desc = "LSZ_D_EU" + eClassOffset;
155  }
156  if (myEmissionClassStrings.hasString(desc)) {
157  return myEmissionClassStrings.get(desc);
158  }
159  return base;
160 }
161 
162 
163 std::string
165  const std::string name = myEmissionClassStrings.getString(c);
166  if (name.find("KKR_") != std::string::npos) {
167  return "Moped";
168  } else if (name.find("RB_") != std::string::npos) {
169  return "Coach";
170  } else if (name.find("LB_") != std::string::npos) {
171  return "UrbanBus";
172  } else if (name.find("LNF_") != std::string::npos) {
173  return "Delivery";
174  } else if (name.find("LSZ_") != std::string::npos) {
175  return "Trailer";
176  } else if (name.find("MR_") != std::string::npos) {
177  return "Motorcycle";
178  } else if (name.find("LKW_") != std::string::npos) {
179  return "Truck";
180  }
181  return "Passenger";
182 }
183 
184 
185 std::string
187  const std::string name = myEmissionClassStrings.getString(c);
188  std::string fuel = "Gasoline";
189  if (name.find("_D_") != std::string::npos) {
190  fuel = "Diesel";
191  }
192  if (name.find("H_") != std::string::npos) {
193  fuel = "Hybrid" + fuel;
194  }
195  return fuel;
196 }
197 
198 
199 int
201  const std::string name = myEmissionClassStrings.getString(c);
202  if (name.find("_EU1") != std::string::npos) {
203  return 1;
204  } else if (name.find("_EU2") != std::string::npos) {
205  return 2;
206  } else if (name.find("_EU3") != std::string::npos) {
207  return 3;
208  } else if (name.find("_EU4") != std::string::npos) {
209  return 4;
210  } else if (name.find("_EU5") != std::string::npos) {
211  return 5;
212  } else if (name.find("_EU6") != std::string::npos) {
213  return 6;
214  }
215  return 0;
216 }
217 
218 
219 double
221  const std::string name = myEmissionClassStrings.getString(c);
222  if (name.find("LNF_") != std::string::npos) {
223  if (name.find("_III") != std::string::npos) {
224  return 2630.;
225  } else if (name.find("_II") != std::string::npos) {
226  return 1532.;
227  } else if (name.find("_I") != std::string::npos) {
228  return 652.;
229  }
230  }
231  if (name.find("Solo_LKW_") != std::string::npos) {
232  if (name.find("_II") != std::string::npos) {
233  return 8398.;
234  } else if (name.find("_I") != std::string::npos) {
235  return 18702.;
236  }
237  }
238  return -1.;
239 }
240 
241 
242 double
243 HelpersPHEMlight::getEmission(const PHEMCEP* oldCep, PHEMlightdll::CEP* currCep, const std::string& e, const double p, const double v) const {
244  if (oldCep != 0) {
245  return oldCep->GetEmission(e, p, v);
246  }
247  return currCep->GetEmission(e, p, v, &myHelper);
248 }
249 
250 
251 double
252 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 {
253  if (c == PHEMLIGHT_BASE) { // zero emission class
254  return 0.;
255  }
256  const double corrSpeed = MAX2((double) 0.0, v);
257  double power = 0.;
258 #ifdef INTERNAL_PHEM
259  const PHEMCEP* const oldCep = PHEMCEPHandler::getHandlerInstance().GetCep(c);
260  if (oldCep != 0) {
261  if (v > IDLE_SPEED && a < oldCep->GetDecelCoast(corrSpeed, a, slope, 0)) {
262  // coasting without power use only works if the engine runs above idle speed and
263  // the vehicle does not accelerate beyond friction losses
264  return 0;
265  }
266  power = oldCep->CalcPower(corrSpeed, a, slope);
267  }
268 #else
269  const PHEMCEP* const oldCep = 0;
270 #endif
271  PHEMlightdll::CEP* currCep = myCEPs.count(c) == 0 ? 0 : myCEPs.find(c)->second;
272  if (currCep != 0) {
273  if (a < currCep->GetDecelCoast(corrSpeed, a, slope) && currCep->getFuelType() != "BEV") {
274  // the IDLE_SPEED fix above is now directly in the decel coast calculation.
275  return 0;
276  }
277  power = currCep->CalcPower(corrSpeed, v == 0.0 ? 0.0 : a, slope);
278  }
279  const std::string& fuelType = oldCep != 0 ? oldCep->GetVehicleFuelType() : currCep->getFuelType();
280  switch (e) {
282  return getEmission(oldCep, currCep, "CO", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
284  if (oldCep != 0) {
285  return getEmission(oldCep, currCep, "FC", power, corrSpeed) * 3.15 / SECONDS_PER_HOUR * 1000.;
286  }
287  return currCep->GetCO2Emission(getEmission(0, currCep, "FC", power, corrSpeed),
288  getEmission(0, currCep, "CO", power, corrSpeed),
289  getEmission(0, currCep, "HC", power, corrSpeed), &myHelper) / SECONDS_PER_HOUR * 1000.;
291  return getEmission(oldCep, currCep, "HC", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
293  return getEmission(oldCep, currCep, "NOx", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
295  return getEmission(oldCep, currCep, "PM", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
297  if (fuelType == "D") { // divide by average diesel density of 836 g/l
298  return getEmission(oldCep, currCep, "FC", power, corrSpeed) / 836. / SECONDS_PER_HOUR * 1000.;
299  } else if (fuelType == "G") { // divide by average gasoline density of 742 g/l
300  return getEmission(oldCep, currCep, "FC", power, corrSpeed) / 742. / SECONDS_PER_HOUR * 1000.;
301  } else if (fuelType == "BEV") {
302  return 0;
303  } else {
304  return getEmission(oldCep, currCep, "FC", power, corrSpeed) / SECONDS_PER_HOUR * 1000.; // surely false, but at least not additionally modified
305  }
306  }
308  if (fuelType == "BEV") {
309  return getEmission(oldCep, currCep, "FC", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
310  }
311  return 0;
312  }
313  // should never get here
314  return 0.;
315 }
316 
317 
318 /****************************************************************************/
Data Handler for a single CEP emission data set.
Definition: PHEMCEP.h:59
void remove(const std::string str, const T key)
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types...
double GetEmission(const std::string &pollutant, double power, double speed, Helpers *VehicleClass)
Definition: CEP.cpp:230
bool hasString(const std::string &str) const
int myIndex
the index of the next class
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...
const std::string & GetVehicleFuelType() const
Getter function to recieve vehicle data from CEP.
Definition: PHEMCEP.h:230
HelpersPHEMlight()
Constructor.
int getEuroClass(const SUMOEmissionClass c) const
Returns the Euro emission class described by this emission class as described in the Amitran interfac...
EmissionType
Enumerating all emission types, including fuel.
#define IDLE_SPEED
T MAX2(T a, T b)
Definition: StdDefs.h:74
bool setclass(const std::string &VEH)
Definition: Helpers.cpp:241
static const int HEAVY_BIT
the bit to set for denoting heavy vehicles
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:65
double getWeight(const SUMOEmissionClass c) const
Returns a reference weight in kg described by this emission class as described in the Amitran interfa...
static PHEMCEPHandler & getHandlerInstance()
Implementatio of Singelton pattern.
std::map< SUMOEmissionClass, PHEMlightdll::CEP * > myCEPs
void insert(const std::string str, const T key, bool checkDuplicates=true)
bool GetCEP(const std::vector< std::string > &DataPath, Helpers *Helper)
Definition: CEPHandler.cpp:43
void addAlias(const std::string str, const T key)
std::string getFuel(const SUMOEmissionClass c) const
Returns the fuel type described by this emission class as described in the Amitran interface (Gasolin...
const std::string & getgClass() const
Definition: Helpers.cpp:63
int SUMOEmissionClass
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...
const std::string & getString(const T key) const
const double SECONDS_PER_HOUR
Definition: PHEMConstants.h:27
static const int PHEMLIGHT_BASE
const std::string & getErrMsg() const
Definition: Helpers.cpp:71
const std::map< std::string, CEP * > & getCEPS() const
Definition: CEPHandler.cpp:39
StringBijection< SUMOEmissionClass > myEmissionClassStrings
Mapping between emission class names and integer representations.
std::string getAmitranVehicleClass(const SUMOEmissionClass c) const
Returns the vehicle class described by this emission class as described in the Amitran interface (Pas...
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:407
SUMOEmissionClass getClassByName(const std::string &eClass, const SUMOVehicleClass vc)
Checks whether the string describes a known vehicle class.
void setCommentPrefix(const std::string &value)
Definition: Helpers.cpp:83
T get(const std::string &str) const
PHEMCEP * GetCep(SUMOEmissionClass emissionClass)
Returns the CEP data for a PHEM emission class.
PHEMlightdll::Helpers myHelper
PHEMlightdll::CEPHandler myCEPHandler
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.
double CalcPower(double speed, double acc, double gradient)
Definition: CEP.cpp:200
const std::string & getFuelType() const
Definition: CEP.cpp:172
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:204
double GetCO2Emission(double _FC, double _CO, double _HC, Helpers *VehicleClass)
Definition: CEP.cpp:291
Helper methods for PHEMlight-based emission computation.
void setPHEMDataV(const std::string &value)
Definition: Helpers.cpp:91