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-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
17 // Helper methods for PHEMlight-based emission computation
18 /****************************************************************************/
19 
20 
21 // ===========================================================================
22 // included modules
23 // ===========================================================================
24 #include <config.h>
25 
26 #include <limits>
27 #include <cmath>
28 #ifdef INTERNAL_PHEM
29 #include "PHEMCEPHandler.h"
30 #include "PHEMConstants.h"
31 #endif
34 #include "HelpersPHEMlight.h"
35 
36 // 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
37 #define IDLE_SPEED (10 / 3.6)
38 
39 // ===========================================================================
40 // method definitions
41 // ===========================================================================
42 HelpersPHEMlight::HelpersPHEMlight() : PollutantsInterface::Helper("PHEMlight"), myIndex(PHEMLIGHT_BASE) {
44 }
45 
46 
48 HelpersPHEMlight::getClassByName(const std::string& eClass, const SUMOVehicleClass vc) {
49  if (eClass == "unknown" && !myEmissionClassStrings.hasString("unknown")) {
50  myEmissionClassStrings.addAlias("unknown", 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  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 != nullptr) {
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 != nullptr) {
277  const double corrAcc = getModifiedAccel(c, corrSpeed, a, slope);
278  if (currCep->getFuelType() != PHEMlightdll::Constants::strBEV && corrAcc < currCep->GetDecelCoast(corrSpeed, corrAcc, slope) && corrSpeed > PHEMlightdll::Constants::ZERO_SPEED_ACCURACY) {
279  // the IDLE_SPEED fix above is now directly in the decel coast calculation.
280  return 0;
281  }
282  power = currCep->CalcPower(corrSpeed, corrAcc, slope);
283  }
284  const std::string& fuelType = oldCep != nullptr ? oldCep->GetVehicleFuelType() : currCep->getFuelType();
285  switch (e) {
287  return getEmission(oldCep, currCep, "CO", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
289  if (oldCep != nullptr) {
290  return getEmission(oldCep, currCep, "FC", power, corrSpeed) * 3.15 / SECONDS_PER_HOUR * 1000.;
291  }
292  return currCep->GetCO2Emission(getEmission(nullptr, currCep, "FC", power, corrSpeed),
293  getEmission(nullptr, currCep, "CO", power, corrSpeed),
294  getEmission(nullptr, currCep, "HC", power, corrSpeed), &myHelper) / SECONDS_PER_HOUR * 1000.;
296  return getEmission(oldCep, currCep, "HC", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
298  return getEmission(oldCep, currCep, "NOx", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
300  return getEmission(oldCep, currCep, "PM", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
302  if (fuelType == PHEMlightdll::Constants::strDiesel) { // divide by average diesel density of 836 g/l
303  return getEmission(oldCep, currCep, "FC", power, corrSpeed) / 836. / SECONDS_PER_HOUR * 1000.;
304  } else if (fuelType == PHEMlightdll::Constants::strGasoline) { // divide by average gasoline density of 742 g/l
305  return getEmission(oldCep, currCep, "FC", power, corrSpeed) / 742. / SECONDS_PER_HOUR * 1000.;
306  } else if (fuelType == PHEMlightdll::Constants::strBEV) {
307  return 0;
308  } else {
309  return getEmission(oldCep, currCep, "FC", power, corrSpeed) / SECONDS_PER_HOUR * 1000.; // surely false, but at least not additionally modified
310  }
311  }
313  if (fuelType == PHEMlightdll::Constants::strBEV) {
314  return getEmission(oldCep, currCep, "FC", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
315  }
316  return 0;
317  }
318  // should never get here
319  return 0.;
320 }
321 
322 
323 /****************************************************************************/
Data Handler for a single CEP emission data set.
Definition: PHEMCEP.h:52
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...
void remove(const std::string str, const T key)
double getWeight(const SUMOEmissionClass c) const
Returns a reference weight in kg described by this emission class as described in the Amitran interfa...
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...
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:227
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:80
bool setclass(const std::string &VEH)
Definition: Helpers.cpp:238
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:400
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
const std::string & getErrMsg() const
Definition: Helpers.cpp:68
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
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:197
bool GetCEP(const std::vector< std::string > &DataPath, Helpers *Helper)
Definition: CEPHandler.cpp:40
void addAlias(const std::string str, const T key)
int SUMOEmissionClass
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...
T get(const std::string &str) const
static const std::string strDiesel
Definition: Constants.h:59
double GetDecelCoast(double speed, double acc, double gradient)
Definition: CEP.cpp:323
T MIN2(T a, T b)
Definition: StdDefs.h:74
const std::string & GetVehicleFuelType() const
Getter function to recieve vehicle data from CEP.
Definition: PHEMCEP.h:223
const double SECONDS_PER_HOUR
Definition: PHEMConstants.h:24
static const int PHEMLIGHT_BASE
static const std::string strGasoline
Definition: Constants.h:58
double GetMaxAccel(double speed, double gradient)
Definition: CEP.cpp:417
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...
static const std::string strBEV
Definition: Constants.h:63
void setCommentPrefix(const std::string &value)
Definition: Helpers.cpp:80
PHEMCEP * GetCep(SUMOEmissionClass emissionClass)
Returns the CEP data for a PHEM emission class.
const std::map< std::string, CEP * > & getCEPS() const
Definition: CEPHandler.cpp:36
PHEMlightdll::Helpers myHelper
PHEMlightdll::CEPHandler myCEPHandler
const std::string & getgClass() const
Definition: Helpers.cpp:60
bool hasString(const std::string &str) const
static const double ZERO_SPEED_ACCURACY
Definition: Constants.h:38
double CalcPower(double speed, double acc, double gradient)
Definition: CEP.cpp:197
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:169
double GetCO2Emission(double _FC, double _CO, double _HC, Helpers *VehicleClass)
Definition: CEP.cpp:288
Helper methods for PHEMlight-based emission computation.
void setPHEMDataV(const std::string &value)
Definition: Helpers.cpp:88