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
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...
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
int myIndex
the index of the next class
const std::string & getString(const T key) const
HelpersPHEMlight()
Constructor.
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
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
std::string getFuel(const SUMOEmissionClass c) const
Returns the fuel type described by this emission class as described in the Amitran interface (Gasolin...
static const int HEAVY_BIT
the bit to set for denoting heavy vehicles
SUMOReal getWeight(const SUMOEmissionClass c) const
Returns a reference weight in kg described by this emission class as described in the Amitran interfa...
const std::string & getErrMsg() const
Definition: Helpers.cpp:47
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)
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
bool GetCEP(const std::vector< std::string > &DataPath, Helpers *Helper)
Definition: CEPHandler.cpp:19
void addAlias(const std::string str, const T key)
int SUMOEmissionClass
T get(const std::string &str) const
const std::string & GetVehicleFuelType() const
Getter function to recieve vehicle data from CEP.
Definition: PHEMCEP.h:230
const double SECONDS_PER_HOUR
Definition: PHEMConstants.h:27
static const int PHEMLIGHT_BASE
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...
StringBijection< SUMOEmissionClass > myEmissionClassStrings
Mapping between emission class names and integer representations.
SUMOEmissionClass getClassByName(const std::string &eClass, const SUMOVehicleClass vc)
Checks whether the string describes a known vehicle class.
int getEuroClass(const SUMOEmissionClass c) const
Returns the Euro emission class described by this emission class as described in the Amitran interfac...
void setCommentPrefix(const std::string &value)
Definition: Helpers.cpp:59
PHEMCEP * GetCep(SUMOEmissionClass emissionClass)
Returns the CEP data for a PHEM emission class.
const std::map< std::string, CEP * > & getCEPS() const
Definition: CEPHandler.cpp:15
PHEMlightdll::Helpers myHelper
#define SUMOReal
Definition: config.h:213
PHEMlightdll::CEPHandler myCEPHandler
const std::string & getgClass() const
Definition: Helpers.cpp:39
bool hasString(const std::string &str) const
double CalcPower(double speed, double acc, double gradient)
Definition: CEP.cpp:176
std::string getAmitranVehicleClass(const SUMOEmissionClass c) const
Returns the vehicle class described by this emission class as described in the Amitran interface (Pas...
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.
const std::string & getFuelType() const
Definition: CEP.cpp:148
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