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-2016 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 #ifdef CHECK_MEMORY_LEAKS
43 #include <foreign/nvwa/debug_new.h>
44 #endif // CHECK_MEMORY_LEAKS
45 
46 // 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
47 #define IDLE_SPEED (10 / 3.6)
48 
49 // ===========================================================================
50 // method definitions
51 // ===========================================================================
52 HelpersPHEMlight::HelpersPHEMlight() : PollutantsInterface::Helper("PHEMlight"), myIndex(PHEMLIGHT_BASE) {
54 }
55 
56 
58 HelpersPHEMlight::getClassByName(const std::string& eClass, const SUMOVehicleClass vc) {
59  if (eClass == "unknown" && !myEmissionClassStrings.hasString("unknown")) {
60  myEmissionClassStrings.addAlias("unknown", getClassByName("PKW_G_EU4", vc));
61  }
62  if (myEmissionClassStrings.hasString(eClass)) {
63  return myEmissionClassStrings.get(eClass);
64  }
65  if (eClass.size() < 6) {
66  throw InvalidArgument("Unknown emission class '" + eClass + "'.");
67  }
68  int index = myIndex++;
69  const std::string type = eClass.substr(0, 3);
70  if (type == "HDV" || type == "LB_" || type == "RB_" || type == "LSZ" || eClass.find("LKW") != std::string::npos) {
72  }
73  myEmissionClassStrings.insert(eClass, index);
74 #ifdef INTERNAL_PHEM
75  if (type == "HDV" || type == "LCV" || type == "PC_" || !PHEMCEPHandler::getHandlerInstance().Load(index, eClass)) {
76 #endif
77  std::vector<std::string> phemPath;
78  phemPath.push_back(OptionsCont::getOptions().getString("phemlight-path") + "/");
79  if (getenv("PHEMLIGHT_PATH") != 0) {
80  phemPath.push_back(std::string(getenv("PHEMLIGHT_PATH")) + "/");
81  }
82  if (getenv("SUMO_HOME") != 0) {
83  phemPath.push_back(std::string(getenv("SUMO_HOME")) + "/data/emissions/PHEMlight/");
84  }
86  myHelper.setPHEMDataV("V4");
87  myHelper.setclass(eClass);
88  if (!myCEPHandler.GetCEP(phemPath, &myHelper)) {
89  myEmissionClassStrings.remove(eClass, index);
90  myIndex--;
91  throw InvalidArgument("File for PHEM emission class " + eClass + " not found.\n" + myHelper.getErrMsg());
92  }
93  myCEPs[index] = myCEPHandler.getCEPS().find(myHelper.getgClass())->second;
94 #ifdef INTERNAL_PHEM
95  }
96 #endif
97  std::string eclower = eClass;
98  std::transform(eclower.begin(), eclower.end(), eclower.begin(), tolower);
99  myEmissionClassStrings.addAlias(eclower, index);
100  return index;
101 }
102 
103 
105 HelpersPHEMlight::getClass(const SUMOEmissionClass base, const std::string& vClass, const std::string& fuel, const std::string& eClass, const double weight) const {
106  std::string eClassOffset = "0";
107  if (eClass.length() == 5 && eClass.substr(0, 4) == "Euro") {
108  if (eClass[4] >= '0' && eClass[4] <= '6') {
109  eClassOffset = eClass.substr(4, 1);
110  }
111  }
112  std::string desc;
113  if (vClass == "Passenger") {
114  desc = "PKW_";
115  if (fuel == "Gasoline") {
116  desc += "G_";
117  } else if (fuel == "Diesel") {
118  desc += "D_";
119  } else if (fuel == "HybridGasoline") {
120  desc = "H_" + desc + "G_";
121  } else if (fuel == "HybridDiesel") {
122  desc = "H_" + desc + "G_";
123  }
124  desc += "EU" + eClassOffset;
125  } else if (vClass == "Moped") {
126  desc = "KKR_G_EU" + eClassOffset;
127  } else if (vClass == "Motorcycle") {
128  desc = "MR_G_EU" + eClassOffset;
129  if (fuel == "Gasoline2S") {
130  desc += "_2T";
131  } else {
132  desc += "_4T";
133  }
134  } else if (vClass == "Delivery") {
135  desc = "LNF_";
136  if (fuel == "Gasoline") {
137  desc += "G_";
138  } else if (fuel == "Diesel") {
139  desc += "D_";
140  }
141  desc += "EU" + eClassOffset + "_I";
142  if (weight > 1305.) {
143  desc += "I";
144  if (weight > 1760.) {
145  desc += "I";
146  }
147  }
148  } else if (vClass == "UrbanBus") {
149  desc = "LB_D_EU" + eClassOffset;
150  } else if (vClass == "Coach") {
151  desc = "RB_D_EU" + eClassOffset;
152  } else if (vClass == "Truck") {
153  desc = "Solo_LKW_D_EU" + eClassOffset + "_I";
154  if (weight > 1305.) {
155  desc += "I";
156  }
157  } else if (vClass == "Trailer") {
158  desc = "LSZ_D_EU" + eClassOffset;
159  }
160  if (myEmissionClassStrings.hasString(desc)) {
161  return myEmissionClassStrings.get(desc);
162  }
163  return base;
164 }
165 
166 
167 std::string
169  const std::string name = myEmissionClassStrings.getString(c);
170  if (name.find("KKR_") != std::string::npos) {
171  return "Moped";
172  } else if (name.find("RB_") != std::string::npos) {
173  return "Coach";
174  } else if (name.find("LB_") != std::string::npos) {
175  return "UrbanBus";
176  } else if (name.find("LNF_") != std::string::npos) {
177  return "Delivery";
178  } else if (name.find("LSZ_") != std::string::npos) {
179  return "Trailer";
180  } else if (name.find("MR_") != std::string::npos) {
181  return "Motorcycle";
182  } else if (name.find("LKW_") != std::string::npos) {
183  return "Truck";
184  }
185  return "Passenger";
186 }
187 
188 
189 std::string
191  const std::string name = myEmissionClassStrings.getString(c);
192  std::string fuel = "Gasoline";
193  if (name.find("_D_") != std::string::npos) {
194  fuel = "Diesel";
195  }
196  if (name.find("H_") != std::string::npos) {
197  fuel = "Hybrid" + fuel;
198  }
199  return fuel;
200 }
201 
202 
203 int
205  const std::string name = myEmissionClassStrings.getString(c);
206  if (name.find("_EU1") != std::string::npos) {
207  return 1;
208  } else if (name.find("_EU2") != std::string::npos) {
209  return 2;
210  } else if (name.find("_EU3") != std::string::npos) {
211  return 3;
212  } else if (name.find("_EU4") != std::string::npos) {
213  return 4;
214  } else if (name.find("_EU5") != std::string::npos) {
215  return 5;
216  } else if (name.find("_EU6") != std::string::npos) {
217  return 6;
218  }
219  return 0;
220 }
221 
222 
223 SUMOReal
225  const std::string name = myEmissionClassStrings.getString(c);
226  if (name.find("LNF_") != std::string::npos) {
227  if (name.find("_III") != std::string::npos) {
228  return 2630.;
229  } else if (name.find("_II") != std::string::npos) {
230  return 1532.;
231  } else if (name.find("_I") != std::string::npos) {
232  return 652.;
233  }
234  }
235  if (name.find("Solo_LKW_") != std::string::npos) {
236  if (name.find("_II") != std::string::npos) {
237  return 8398.;
238  } else if (name.find("_I") != std::string::npos) {
239  return 18702.;
240  }
241  }
242  return -1.;
243 }
244 
245 
246 SUMOReal
247 HelpersPHEMlight::getEmission(const PHEMCEP* oldCep, PHEMlightdll::CEP* currCep, const std::string& e, const double p, const double v) const {
248  if (oldCep != 0) {
249  return oldCep->GetEmission(e, p, v);
250  }
251  return currCep->GetEmission(e, p, v, &myHelper);
252 }
253 
254 
255 SUMOReal
256 HelpersPHEMlight::compute(const SUMOEmissionClass c, const PollutantsInterface::EmissionType e, const double v, const double a, const double slope) const {
257  if (c == PHEMLIGHT_BASE) { // zero emission class
258  return 0.;
259  }
260  const double corrSpeed = MAX2((double) 0.0, v);
261  double power = 0.;
262 #ifdef INTERNAL_PHEM
263  const PHEMCEP* const oldCep = PHEMCEPHandler::getHandlerInstance().GetCep(c);
264  if (oldCep != 0) {
265  if (v > IDLE_SPEED && a < oldCep->GetDecelCoast(corrSpeed, a, slope, 0)) {
266  // coasting without power use only works if the engine runs above idle speed and
267  // the vehicle does not accelerate beyond friction losses
268  return 0;
269  }
270  power = oldCep->CalcPower(corrSpeed, a, slope);
271  }
272 #else
273  const PHEMCEP* const oldCep = 0;
274 #endif
275  PHEMlightdll::CEP* currCep = myCEPs.count(c) == 0 ? 0 : myCEPs.find(c)->second;
276  if (currCep != 0) {
277  if (a < currCep->GetDecelCoast(corrSpeed, a, slope) && currCep->getFuelType() != "BEV") {
278  // the IDLE_SPEED fix above is now directly in the decel coast calculation.
279  return 0;
280  }
281  power = currCep->CalcPower(corrSpeed, v == 0.0 ? 0.0 : a, slope);
282  }
283  const std::string& fuelType = oldCep != 0 ? oldCep->GetVehicleFuelType() : currCep->getFuelType();
284  switch (e) {
286  return getEmission(oldCep, currCep, "CO", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
288  if (oldCep != 0) {
289  return getEmission(oldCep, currCep, "FC", power, corrSpeed) * 3.15 / SECONDS_PER_HOUR * 1000.;
290  }
291  return currCep->GetCO2Emission(getEmission(0, currCep, "FC", power, corrSpeed),
292  getEmission(0, currCep, "CO", power, corrSpeed),
293  getEmission(0, 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 == "D") { // 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 == "G") { // 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 == "BEV") {
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 == "BEV") {
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 /****************************************************************************/
323 
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:206
bool hasString(const std::string &str) const
int myIndex
the index of the next class
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:75
bool setclass(const std::string &VEH)
Definition: Helpers.cpp:217
SUMOReal compute(const SUMOEmissionClass c, const PollutantsInterface::EmissionType e, const double v, const double a, const double slope) const
Returns the amount of emitted pollutant given the vehicle type and state (in mg/s or in ml/s for fuel...
SUMOReal getWeight(const SUMOEmissionClass c) const
Returns a reference weight in kg described by this emission class as described in the Amitran interfa...
static const int HEAVY_BIT
the bit to set for denoting heavy vehicles
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:69
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:19
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...
SUMOReal 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 & getgClass() const
Definition: Helpers.cpp:39
int SUMOEmissionClass
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:47
const std::map< std::string, CEP * > & getCEPS() const
Definition: CEPHandler.cpp:15
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:411
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:59
T get(const std::string &str) const
PHEMCEP * GetCep(SUMOEmissionClass emissionClass)
Returns the CEP data for a PHEM emission class.
PHEMlightdll::Helpers myHelper
#define SUMOReal
Definition: config.h:213
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:176
const std::string & getFuelType() const
Definition: CEP.cpp:148
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:208
double GetCO2Emission(double _FC, double _CO, double _HC, Helpers *VehicleClass)
Definition: CEP.cpp:267
Helper methods for PHEMlight-based emission computation.
void setPHEMDataV(const std::string &value)
Definition: Helpers.cpp:67