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-2024 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 EnergyParams* /* param */) 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, param);
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
int SUMOEmissionClass
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
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 EnergyParams *param) 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.