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-2017 German Aerospace Center (DLR) and others.
4 /****************************************************************************/
5 //
6 // This program and the accompanying materials
7 // are made available under the terms of the Eclipse Public License v2.0
8 // which accompanies this distribution, and is available at
9 // http://www.eclipse.org/legal/epl-v20.html
10 //
11 /****************************************************************************/
19 // Helper methods for PHEMlight-based emission computation
20 /****************************************************************************/
21 
22 
23 // ===========================================================================
24 // included modules
25 // ===========================================================================
26 #ifdef _MSC_VER
27 #include <windows_config.h>
28 #else
29 #include <config.h>
30 #endif
31 
32 #include <limits>
33 #include <cmath>
34 #ifdef INTERNAL_PHEM
35 #include "PHEMCEPHandler.h"
36 #include "PHEMConstants.h"
37 #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::getModifiedAccel(const SUMOEmissionClass c, const double v, const double a, const double slope) const {
253  PHEMlightdll::CEP* currCep = myCEPs.count(c) == 0 ? 0 : myCEPs.find(c)->second;
254  if (currCep != 0) {
255  return v == 0.0 ? 0.0 : MIN2(a, currCep->GetMaxAccel(v, slope));
256  }
257  return a;
258 }
259 
260 
261 double
262 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 {
263  if (c == PHEMLIGHT_BASE) { // zero emission class
264  return 0.;
265  }
266  const double corrSpeed = MAX2((double) 0.0, v);
267  double power = 0.;
268 #ifdef INTERNAL_PHEM
269  const PHEMCEP* const oldCep = PHEMCEPHandler::getHandlerInstance().GetCep(c);
270  if (oldCep != 0) {
271  if (v > IDLE_SPEED && a < oldCep->GetDecelCoast(corrSpeed, a, slope, 0)) {
272  // coasting without power use only works if the engine runs above idle speed and
273  // the vehicle does not accelerate beyond friction losses
274  return 0;
275  }
276  power = oldCep->CalcPower(corrSpeed, a, slope);
277  }
278 #else
279  const PHEMCEP* const oldCep = 0;
280 #endif
281  PHEMlightdll::CEP* currCep = myCEPs.count(c) == 0 ? 0 : myCEPs.find(c)->second;
282  if (currCep != 0) {
283  const double corrAcc = getModifiedAccel(c, corrSpeed, a, slope);
284  if (currCep->getFuelType() != PHEMlightdll::Constants::strBEV && corrAcc < currCep->GetDecelCoast(corrSpeed, corrAcc, slope) && corrSpeed > PHEMlightdll::Constants::ZERO_SPEED_ACCURACY) {
285  // the IDLE_SPEED fix above is now directly in the decel coast calculation.
286  return 0;
287  }
288  power = currCep->CalcPower(corrSpeed, corrAcc, slope);
289  }
290  const std::string& fuelType = oldCep != 0 ? oldCep->GetVehicleFuelType() : currCep->getFuelType();
291  switch (e) {
293  return getEmission(oldCep, currCep, "CO", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
295  if (oldCep != 0) {
296  return getEmission(oldCep, currCep, "FC", power, corrSpeed) * 3.15 / SECONDS_PER_HOUR * 1000.;
297  }
298  return currCep->GetCO2Emission(getEmission(0, currCep, "FC", power, corrSpeed),
299  getEmission(0, currCep, "CO", power, corrSpeed),
300  getEmission(0, currCep, "HC", power, corrSpeed), &myHelper) / SECONDS_PER_HOUR * 1000.;
302  return getEmission(oldCep, currCep, "HC", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
304  return getEmission(oldCep, currCep, "NOx", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
306  return getEmission(oldCep, currCep, "PM", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
308  if (fuelType == PHEMlightdll::Constants::strDiesel) { // divide by average diesel density of 836 g/l
309  return getEmission(oldCep, currCep, "FC", power, corrSpeed) / 836. / SECONDS_PER_HOUR * 1000.;
310  } else if (fuelType == PHEMlightdll::Constants::strGasoline) { // divide by average gasoline density of 742 g/l
311  return getEmission(oldCep, currCep, "FC", power, corrSpeed) / 742. / SECONDS_PER_HOUR * 1000.;
312  } else if (fuelType == PHEMlightdll::Constants::strBEV) {
313  return 0;
314  } else {
315  return getEmission(oldCep, currCep, "FC", power, corrSpeed) / SECONDS_PER_HOUR * 1000.; // surely false, but at least not additionally modified
316  }
317  }
319  if (fuelType == PHEMlightdll::Constants::strBEV) {
320  return getEmission(oldCep, currCep, "FC", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
321  }
322  return 0;
323  }
324  // should never get here
325  return 0.;
326 }
327 
328 
329 /****************************************************************************/
Data Handler for a single CEP emission data set.
Definition: PHEMCEP.h:58
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:229
bool hasString(const std::string &str) const
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 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:229
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:73
bool setclass(const std::string &VEH)
Definition: Helpers.cpp:240
static const int HEAVY_BIT
the bit to set for denoting heavy vehicles
C++ TraCI client API implementation.
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:64
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:42
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:62
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
static const std::string strDiesel
Definition: Constants.h:61
double GetDecelCoast(double speed, double acc, double gradient)
Definition: CEP.cpp:325
T MIN2(T a, T b)
Definition: StdDefs.h:67
const double SECONDS_PER_HOUR
Definition: PHEMConstants.h:26
static const int PHEMLIGHT_BASE
static const std::string strGasoline
Definition: Constants.h:60
const std::string & getErrMsg() const
Definition: Helpers.cpp:70
double GetMaxAccel(double speed, double gradient)
Definition: CEP.cpp:419
const std::map< std::string, CEP * > & getCEPS() const
Definition: CEPHandler.cpp:38
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:406
SUMOEmissionClass getClassByName(const std::string &eClass, const SUMOVehicleClass vc)
Checks whether the string describes a known vehicle class.
static const std::string strBEV
Definition: Constants.h:65
void setCommentPrefix(const std::string &value)
Definition: Helpers.cpp:82
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.
static const double ZERO_SPEED_ACCURACY
Definition: Constants.h:40
double CalcPower(double speed, double acc, double gradient)
Definition: CEP.cpp:199
const std::string & getFuelType() const
Definition: CEP.cpp:171
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:203
double GetCO2Emission(double _FC, double _CO, double _HC, Helpers *VehicleClass)
Definition: CEP.cpp:290
Helper methods for PHEMlight-based emission computation.
void setPHEMDataV(const std::string &value)
Definition: Helpers.cpp:90