Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
HelpersPHEMlight.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2013-2023 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
20// Helper methods for PHEMlight-based emission computation
21/****************************************************************************/
22#include <config.h>
23
24#include <limits>
25#include <cmath>
26#ifdef INTERNAL_PHEM
27#include "PHEMCEPHandler.h"
28#include "PHEMConstants.h"
29#endif
33
34#include "EnergyParams.h"
35#include "HelpersPHEMlight.h"
36
37// 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
38#define IDLE_SPEED (10 / 3.6)
39
40// ===========================================================================
41// method definitions
42// ===========================================================================
44 PollutantsInterface::Helper("PHEMlight", PHEMLIGHT_BASE, -1),
45 myIndex(PHEMLIGHT_BASE) {
46}
47
48
50 for (const auto& cep : myCEPs) {
51 delete cep.second;
52 }
53}
54
55
57HelpersPHEMlight::getClassByName(const std::string& eClass, const SUMOVehicleClass vc) {
58 if (eClass == "unknown" && !myEmissionClassStrings.hasString("unknown")) {
59 myEmissionClassStrings.addAlias("unknown", getClassByName("PC_G_EU4", vc));
60 }
61 if (eClass == "default" && !myEmissionClassStrings.hasString("default")) {
62 myEmissionClassStrings.addAlias("default", getClassByName("PC_G_EU4", vc));
63 }
65 return myEmissionClassStrings.get(eClass);
66 }
67 if (eClass.size() < 6) {
68 throw InvalidArgument("Unknown emission class '" + eClass + "'.");
69 }
70 int index = myIndex++;
71 const std::string type = eClass.substr(0, 3);
72 if (type == "HDV" || type == "LB_" || type == "RB_" || type == "LSZ" || eClass.find("LKW") != std::string::npos) {
74 }
75 myEmissionClassStrings.insert(eClass, index);
76#ifdef INTERNAL_PHEM
77 if (type == "HDV" || type == "LCV" || type == "PC_" || !PHEMCEPHandler::getHandlerInstance().Load(index, eClass)) {
78#endif
79 myVolumetricFuel = OptionsCont::getOptions().getBool("emissions.volumetric-fuel");
80 std::vector<std::string> phemPath;
81 phemPath.push_back(OptionsCont::getOptions().getString("phemlight-path") + "/");
82 if (getenv("PHEMLIGHT_PATH") != nullptr) {
83 phemPath.push_back(std::string(getenv("PHEMLIGHT_PATH")) + "/");
84 }
85 if (getenv("SUMO_HOME") != nullptr) {
86 phemPath.push_back(std::string(getenv("SUMO_HOME")) + "/data/emissions/PHEMlight/");
87 }
90 myHelper.setclass(eClass);
91 if (!myCEPHandler.GetCEP(phemPath, &myHelper)) {
92 myEmissionClassStrings.remove(eClass, index);
93 myIndex--;
94 throw InvalidArgument("File for PHEM emission class " + eClass + " not found.\n" + myHelper.getErrMsg());
95 }
96 myCEPs[index] = myCEPHandler.getCEPS().find(myHelper.getgClass())->second;
97#ifdef INTERNAL_PHEM
98 }
99#endif
101 return index;
102}
103
104
106HelpersPHEMlight::getClass(const SUMOEmissionClass base, const std::string& vClass, const std::string& fuel, const std::string& eClass, const double weight) const {
107 std::string eClassOffset = "0";
108 if (eClass.length() == 5 && eClass.substr(0, 4) == "Euro") {
109 if (eClass[4] >= '0' && eClass[4] <= '6') {
110 eClassOffset = eClass.substr(4, 1);
111 }
112 }
113 std::string desc;
114 if (vClass == "Passenger") {
115 desc = "PKW_";
116 if (fuel == "Gasoline") {
117 desc += "G_";
118 } else if (fuel == "Diesel") {
119 desc += "D_";
120 } else if (fuel == "HybridGasoline") {
121 desc = "H_" + desc + "G_";
122 } else if (fuel == "HybridDiesel") {
123 desc = "H_" + desc + "G_";
124 }
125 desc += "EU" + eClassOffset;
126 } else if (vClass == "Moped") {
127 desc = "KKR_G_EU" + eClassOffset;
128 } else if (vClass == "Motorcycle") {
129 desc = "MR_G_EU" + eClassOffset;
130 if (fuel == "Gasoline2S") {
131 desc += "_2T";
132 } else {
133 desc += "_4T";
134 }
135 } else if (vClass == "Delivery") {
136 desc = "LNF_";
137 if (fuel == "Gasoline") {
138 desc += "G_";
139 } else if (fuel == "Diesel") {
140 desc += "D_";
141 }
142 desc += "EU" + eClassOffset + "_I";
143 if (weight > 1305.) {
144 desc += "I";
145 if (weight > 1760.) {
146 desc += "I";
147 }
148 }
149 } else if (vClass == "UrbanBus") {
150 desc = "LB_D_EU" + eClassOffset;
151 } else if (vClass == "Coach") {
152 desc = "RB_D_EU" + eClassOffset;
153 } else if (vClass == "Truck") {
154 desc = "Solo_LKW_D_EU" + eClassOffset + "_I";
155 if (weight > 1305.) {
156 desc += "I";
157 }
158 } else if (vClass == "Trailer") {
159 desc = "LSZ_D_EU" + eClassOffset;
160 }
162 return myEmissionClassStrings.get(desc);
163 }
164 return base;
165}
166
167
168std::string
170 const std::string name = myEmissionClassStrings.getString(c);
171 if (name.find("KKR_") != std::string::npos) {
172 return "Moped";
173 } else if (name.find("RB_") != std::string::npos) {
174 return "Coach";
175 } else if (name.find("LB_") != std::string::npos) {
176 return "UrbanBus";
177 } else if (name.find("LNF_") != std::string::npos) {
178 return "Delivery";
179 } else if (name.find("LSZ_") != std::string::npos) {
180 return "Trailer";
181 } else if (name.find("MR_") != std::string::npos) {
182 return "Motorcycle";
183 } else if (name.find("LKW_") != std::string::npos) {
184 return "Truck";
185 }
186 return "Passenger";
187}
188
189
190std::string
192 const std::string name = myEmissionClassStrings.getString(c);
193 std::string fuel = "Gasoline";
194 if (name.find("_D_") != std::string::npos) {
195 fuel = "Diesel";
196 }
197 if (name.find("H_") != std::string::npos) {
198 fuel = "Hybrid" + fuel;
199 }
200 return fuel;
201}
202
203
204int
206 const std::string name = myEmissionClassStrings.getString(c);
207 if (name.find("_EU1") != std::string::npos) {
208 return 1;
209 } else if (name.find("_EU2") != std::string::npos) {
210 return 2;
211 } else if (name.find("_EU3") != std::string::npos) {
212 return 3;
213 } else if (name.find("_EU4") != std::string::npos) {
214 return 4;
215 } else if (name.find("_EU5") != std::string::npos) {
216 return 5;
217 } else if (name.find("_EU6") != std::string::npos) {
218 return 6;
219 }
220 return 0;
221}
222
223
224double
226 const std::string name = myEmissionClassStrings.getString(c);
227 if (name.find("LNF_") != std::string::npos) {
228 if (name.find("_III") != std::string::npos) {
229 return 2630.;
230 } else if (name.find("_II") != std::string::npos) {
231 return 1532.;
232 } else if (name.find("_I") != std::string::npos) {
233 return 652.;
234 }
235 }
236 if (name.find("Solo_LKW_") != std::string::npos) {
237 if (name.find("_II") != std::string::npos) {
238 return 8398.;
239 } else if (name.find("_I") != std::string::npos) {
240 return 18702.;
241 }
242 }
243 return -1.;
244}
245
246
247double
248HelpersPHEMlight::getEmission(const PHEMCEP* oldCep, PHEMlightdll::CEP* currCep, const std::string& e, const double p, const double v) const {
249 if (oldCep != nullptr) {
250 return oldCep->GetEmission(e, p, v);
251 }
252 return currCep->GetEmission(e, p, v, &myHelper);
253}
254
255
256double
257HelpersPHEMlight::getModifiedAccel(const SUMOEmissionClass c, const double v, const double a, const double slope) const {
258 PHEMlightdll::CEP* currCep = myCEPs.count(c) == 0 ? 0 : myCEPs.find(c)->second;
259 if (currCep != nullptr) {
260 return v == 0.0 ? 0.0 : MIN2(a, currCep->GetMaxAccel(v, slope));
261 }
262 return a;
263}
264
265
266double
267HelpersPHEMlight::getCoastingDecel(const SUMOEmissionClass c, const double v, const double a, const double slope, const EnergyParams* /* param */) const {
268 return myCEPs.count(c) == 0 ? 0. : myCEPs.find(c)->second->GetDecelCoast(v, a, slope);
269}
270
271
272double
273HelpersPHEMlight::compute(const SUMOEmissionClass c, const PollutantsInterface::EmissionType e, const double v, const double a, const double slope, const EnergyParams* param) const {
274 if (param != nullptr && param->isEngineOff()) {
275 return 0.;
276 }
277 const double corrSpeed = MAX2(0.0, v);
278 double power = 0.;
279#ifdef INTERNAL_PHEM
280 const PHEMCEP* const oldCep = PHEMCEPHandler::getHandlerInstance().GetCep(c);
281 if (oldCep != nullptr) {
282 if (v > IDLE_SPEED && a < oldCep->GetDecelCoast(corrSpeed, a, slope, 0)) {
283 // coasting without power use only works if the engine runs above idle speed and
284 // the vehicle does not accelerate beyond friction losses
285 return 0;
286 }
287 power = oldCep->CalcPower(corrSpeed, a, slope);
288 }
289#else
290 const PHEMCEP* const oldCep = 0;
291#endif
292 PHEMlightdll::CEP* currCep = myCEPs.count(c) == 0 ? 0 : myCEPs.find(c)->second;
293 if (currCep != nullptr) {
294 const double corrAcc = getModifiedAccel(c, corrSpeed, a, slope);
296 corrAcc < currCep->GetDecelCoast(corrSpeed, corrAcc, slope) &&
298 // the IDLE_SPEED fix above is now directly in the decel coast calculation.
299 return 0;
300 }
301 power = currCep->CalcPower(corrSpeed, corrAcc, slope);
302 }
303 const std::string& fuelType = oldCep != nullptr ? oldCep->GetVehicleFuelType() : currCep->getFuelType();
304 switch (e) {
306 return getEmission(oldCep, currCep, "CO", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
308 if (oldCep != nullptr) {
309 return getEmission(oldCep, currCep, "FC", power, corrSpeed) * 3.15 / SECONDS_PER_HOUR * 1000.;
310 }
311 return currCep->GetCO2Emission(getEmission(nullptr, currCep, "FC", power, corrSpeed),
312 getEmission(nullptr, currCep, "CO", power, corrSpeed),
313 getEmission(nullptr, currCep, "HC", power, corrSpeed), &myHelper) / SECONDS_PER_HOUR * 1000.;
315 return getEmission(oldCep, currCep, "HC", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
317 return getEmission(oldCep, currCep, "NOx", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
319 return getEmission(oldCep, currCep, "PM", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
321 if (myVolumetricFuel && fuelType == PHEMlightdll::Constants::strDiesel) { // divide by average diesel density of 836 g/l
322 return getEmission(oldCep, currCep, "FC", power, corrSpeed) / 836. / SECONDS_PER_HOUR * 1000.;
323 }
324 if (myVolumetricFuel && fuelType == PHEMlightdll::Constants::strGasoline) { // divide by average gasoline density of 742 g/l
325 return getEmission(oldCep, currCep, "FC", power, corrSpeed) / 742. / SECONDS_PER_HOUR * 1000.;
326 }
327 if (fuelType == PHEMlightdll::Constants::strBEV) {
328 return 0.;
329 }
330 return getEmission(oldCep, currCep, "FC", power, corrSpeed) / SECONDS_PER_HOUR * 1000.; // still in mg even if myVolumetricFuel is set!
331 }
333 if (fuelType == PHEMlightdll::Constants::strBEV) {
334 return getEmission(oldCep, currCep, "FC", power, corrSpeed) / SECONDS_PER_HOUR * 1000.;
335 }
336 return 0;
337 }
338 // should never get here
339 return 0.;
340}
341
342
343/****************************************************************************/
#define IDLE_SPEED
const double SECONDS_PER_HOUR
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
int SUMOEmissionClass
T MIN2(T a, T b)
Definition StdDefs.h:76
T MAX2(T a, T b)
Definition StdDefs.h:82
An upper class for objects with additional parameters.
bool isEngineOff() const
Returns the state of the engine when the vehicle is not moving.
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...
std::map< SUMOEmissionClass, PHEMlightdll::CEP * > myCEPs
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.
std::string getFuel(const SUMOEmissionClass c) const
Returns the fuel type described by this emission class as described in the Amitran interface (Gasolin...
PHEMlightdll::Helpers myHelper
virtual double compute(const SUMOEmissionClass c, const PollutantsInterface::EmissionType e, const double v, const double a, const double slope, const EnergyParams *param) const
Returns the amount of emitted pollutant given the vehicle type and state (in mg/s or in ml/s for fuel...
HelpersPHEMlight()
Constructor.
virtual 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.
virtual double getCoastingDecel(const SUMOEmissionClass c, const double v, const double a, const double slope, const EnergyParams *param) const
Returns the maximum deceleration value (as a negative number), which can still be considered as non-b...
int getEuroClass(const SUMOEmissionClass c) const
Returns the Euro emission class described by this emission class as described in the Amitran interfac...
virtual ~HelpersPHEMlight()
Destructor.
virtual SUMOEmissionClass getClassByName(const std::string &eClass, const SUMOVehicleClass vc)
Checks whether the string describes a known vehicle class.
double getWeight(const SUMOEmissionClass c) const
Returns a reference weight in kg described by this emission class as described in the Amitran interfa...
PHEMlightdll::CEPHandler myCEPHandler
int myIndex
the index of the next class
std::string getAmitranVehicleClass(const SUMOEmissionClass c) const
Returns the vehicle class described by this emission class as described in the Amitran interface (Pas...
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
static OptionsCont & getOptions()
Retrieves the options.
static PHEMCEPHandler & getHandlerInstance()
Implementatio of Singelton pattern.
PHEMCEP * GetCep(SUMOEmissionClass emissionClass)
Returns the CEP data for a PHEM emission class.
Data Handler for a single CEP emission data set.
Definition PHEMCEP.h:49
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:399
const std::string & GetVehicleFuelType() const
Getter function to recieve vehicle data from CEP.
Definition PHEMCEP.h:220
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:196
const std::map< std::string, CEP * > & getCEPS() const
bool GetCEP(const std::vector< std::string > &DataPath, Helpers *Helper)
double GetMaxAccel(double speed, double gradient)
Definition cpp/CEP.cpp:420
double GetEmission(const std::string &pollutant, double power, double speed, Helpers *VehicleClass)
Definition cpp/CEP.cpp:230
double CalcPower(double speed, double acc, double gradient)
Definition cpp/CEP.cpp:200
const std::string & getFuelType() const
Definition cpp/CEP.cpp:172
double GetCO2Emission(double _FC, double _CO, double _HC, Helpers *VehicleClass)
Definition cpp/CEP.cpp:291
static const std::string strBEV
static const double ZERO_SPEED_ACCURACY
static const std::string strDiesel
static const std::string strGasoline
const std::string & getErrMsg() const
void setPHEMDataV(const std::string &value)
void setCommentPrefix(const std::string &value)
const std::string & getgClass() const
bool setclass(const std::string &VEH)
bool myVolumetricFuel
return fuel consumption in l instead of mg
StringBijection< SUMOEmissionClass > myEmissionClassStrings
Mapping between emission class names and integer representations.
Helper methods for PHEMlight-based emission computation.
EmissionType
Enumerating all emission types, including fuel.
static const int HEAVY_BIT
the bit to set for denoting heavy vehicles
const std::string & getString(const T key) const
void remove(const std::string str, const T key)
bool hasString(const std::string &str) const
void addAlias(const std::string str, const T key)
T get(const std::string &str) const
void insert(const std::string str, const T key, bool checkDuplicates=true)
static std::string to_lower_case(const std::string &str)
Transfers the content to lower case.