Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/utils/emissions/PollutantsInterface.cpp
169678 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2013-2025 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
/****************************************************************************/
14
/// @file PollutantsInterface.cpp
15
/// @author Daniel Krajzewicz
16
/// @author Michael Behrisch
17
/// @date Mon, 19.08.2013
18
///
19
// Interface to capsulate different emission models
20
/****************************************************************************/
21
#include <config.h>
22
23
#include <limits>
24
#include <cmath>
25
#include <utils/common/MsgHandler.h>
26
#include <utils/common/SUMOVehicleClass.h>
27
#include <utils/common/StringUtils.h>
28
#include <utils/common/ToString.h>
29
#include <utils/options/OptionsCont.h>
30
#include <foreign/PHEMlight/V5/cpp/Constants.h>
31
32
#include "HelpersHBEFA.h"
33
#include "HelpersHBEFA3.h"
34
#include "HelpersHBEFA4.h"
35
#include "HelpersPHEMlight.h"
36
#include "HelpersEnergy.h"
37
#include "HelpersMMPEVEM.h"
38
#include "HelpersPHEMlight5.h"
39
#include "PollutantsInterface.h"
40
41
42
// ===========================================================================
43
// static definitions
44
// ===========================================================================
45
const double PollutantsInterface::Helper::ZERO_SPEED_ACCURACY = .5;
46
PollutantsInterface::Helper PollutantsInterface::myZeroHelper("Zero", PollutantsInterface::ZERO_EMISSIONS, PollutantsInterface::ZERO_EMISSIONS);
47
HelpersHBEFA PollutantsInterface::myHBEFA2Helper;
48
HelpersHBEFA3 PollutantsInterface::myHBEFA3Helper;
49
HelpersPHEMlight PollutantsInterface::myPHEMlightHelper;
50
HelpersEnergy PollutantsInterface::myEnergyHelper;
51
HelpersMMPEVEM PollutantsInterface::myMMPEVEMHelper;
52
HelpersPHEMlight5 PollutantsInterface::myPHEMlight5Helper;
53
HelpersHBEFA4 PollutantsInterface::myHBEFA4Helper;
54
PollutantsInterface::Helper* PollutantsInterface::myHelpers[] = {
55
&PollutantsInterface::myZeroHelper,
56
&PollutantsInterface::myHBEFA2Helper, &PollutantsInterface::myHBEFA3Helper,
57
&PollutantsInterface::myPHEMlightHelper, &PollutantsInterface::myEnergyHelper,
58
&PollutantsInterface::myMMPEVEMHelper, &PollutantsInterface::myPHEMlight5Helper,
59
&PollutantsInterface::myHBEFA4Helper
60
};
61
std::vector<std::string> PollutantsInterface::myAllClassesStr;
62
63
64
// ===========================================================================
65
// method definitions
66
// ===========================================================================
67
68
// ---------------------------------------------------------------------------
69
// PollutantsInterface::Emissions - methods
70
// ---------------------------------------------------------------------------
71
72
PollutantsInterface::Emissions::Emissions(double co2, double co, double hc, double f, double nox, double pmx, double elec) :
73
CO2(co2),
74
CO(co),
75
HC(hc),
76
fuel(f),
77
NOx(nox),
78
PMx(pmx),
79
electricity(elec) {
80
}
81
82
83
void PollutantsInterface::Emissions::addScaled(const Emissions& a, const double scale) {
84
CO2 += scale * a.CO2;
85
CO += scale * a.CO;
86
HC += scale * a.HC;
87
fuel += scale * a.fuel;
88
NOx += scale * a.NOx;
89
PMx += scale * a.PMx;
90
electricity += scale * a.electricity;
91
}
92
93
// ---------------------------------------------------------------------------
94
// PollutantsInterface::Helper - methods
95
// ---------------------------------------------------------------------------
96
97
PollutantsInterface::Helper::Helper(std::string name, const int baseIndex, const int defaultClass) :
98
myName(name),
99
myBaseIndex(baseIndex) {
100
if (defaultClass != -1) {
101
myEmissionClassStrings.insert("default", defaultClass);
102
myEmissionClassStrings.addAlias("unknown", defaultClass);
103
}
104
}
105
106
107
const
108
std::string& PollutantsInterface::Helper::getName() const {
109
return myName;
110
}
111
112
113
SUMOEmissionClass
114
PollutantsInterface::Helper::getClassByName(const std::string& eClass, const SUMOVehicleClass vc) {
115
UNUSED_PARAMETER(vc);
116
myVolumetricFuel = OptionsCont::getOptions().exists("emissions.volumetric-fuel") && OptionsCont::getOptions().getBool("emissions.volumetric-fuel");
117
if (myEmissionClassStrings.hasString(eClass)) {
118
return myEmissionClassStrings.get(eClass);
119
}
120
return myEmissionClassStrings.get(StringUtils::to_lower_case(eClass));
121
}
122
123
124
const std::string
125
PollutantsInterface::Helper::getClassName(const SUMOEmissionClass c) const {
126
return myName + "/" + myEmissionClassStrings.getString(c);
127
}
128
129
130
bool
131
PollutantsInterface::Helper::isSilent(const SUMOEmissionClass c) {
132
return (c & (int)0xffffffff & ~HEAVY_BIT) == 0;
133
}
134
135
136
SUMOEmissionClass
137
PollutantsInterface::Helper::getClass(const SUMOEmissionClass base, const std::string& vClass, const std::string& fuel, const std::string& eClass, const double weight) const {
138
UNUSED_PARAMETER(vClass);
139
UNUSED_PARAMETER(fuel);
140
UNUSED_PARAMETER(eClass);
141
UNUSED_PARAMETER(weight);
142
return base;
143
}
144
145
146
std::string
147
PollutantsInterface::Helper::getAmitranVehicleClass(const SUMOEmissionClass c) const {
148
UNUSED_PARAMETER(c);
149
return "Passenger";
150
}
151
152
153
std::string
154
PollutantsInterface::Helper::getFuel(const SUMOEmissionClass c) const {
155
UNUSED_PARAMETER(c);
156
return "Gasoline";
157
}
158
159
160
int
161
PollutantsInterface::Helper::getEuroClass(const SUMOEmissionClass c) const {
162
UNUSED_PARAMETER(c);
163
return 0;
164
}
165
166
167
double
168
PollutantsInterface::Helper::getWeight(const SUMOEmissionClass c) const {
169
UNUSED_PARAMETER(c);
170
return -1.;
171
}
172
173
174
double
175
PollutantsInterface::Helper::compute(const SUMOEmissionClass c, const EmissionType e, const double v, const double a, const double slope, const EnergyParams* param) const {
176
UNUSED_PARAMETER(c);
177
UNUSED_PARAMETER(e);
178
UNUSED_PARAMETER(v);
179
UNUSED_PARAMETER(a);
180
UNUSED_PARAMETER(slope);
181
UNUSED_PARAMETER(param);
182
return 0.;
183
}
184
185
186
double
187
PollutantsInterface::Helper::getModifiedAccel(const SUMOEmissionClass c, const double v, const double a, const double slope, const EnergyParams* param) const {
188
UNUSED_PARAMETER(c);
189
UNUSED_PARAMETER(v);
190
UNUSED_PARAMETER(slope);
191
UNUSED_PARAMETER(param);
192
return a;
193
}
194
195
196
double
197
PollutantsInterface::Helper::getCoastingDecel(const SUMOEmissionClass c, const double v, const double a, const double slope, const EnergyParams* param) const {
198
// the interpolation for small v is basically the same as in PHEMlightdllV5::CEP::GetDecelCoast
199
if (v < PHEMlightdllV5::Constants::SPEED_DCEL_MIN) {
200
return v / PHEMlightdllV5::Constants::SPEED_DCEL_MIN * getCoastingDecel(c, PHEMlightdllV5::Constants::SPEED_DCEL_MIN, a, slope, param);
201
}
202
if (param == nullptr) {
203
param = EnergyParams::getDefault();
204
}
205
// the magic numbers below come from a linear interpolation with http://ts-sim-service-ba/svn/simo/trunk/projects/sumo/data/emissions/linear.py
206
const double mass = param->getDouble(SUMO_ATTR_MASS);
207
const double incl = param->getDouble(SUMO_ATTR_FRONTSURFACEAREA) / mass * -9.05337017 + -0.00017774;
208
const double grad = slope == 0. ? 0. : PHEMlightdllV5::Constants::GRAVITY_CONST * sin(DEG2RAD(slope));
209
return MIN2(0., incl * v + 0.00001066 * mass + -0.38347107 - 20.0 * incl - grad);
210
}
211
212
213
void
214
PollutantsInterface::Helper::addAllClassesInto(std::vector<SUMOEmissionClass>& list) const {
215
myEmissionClassStrings.addKeysInto(list);
216
}
217
218
219
bool
220
PollutantsInterface::Helper::includesClass(const SUMOEmissionClass c) const {
221
return (c >> 16) == (myBaseIndex >> 16);
222
}
223
224
// ---------------------------------------------------------------------------
225
// PollutantsInterface - methods
226
// ---------------------------------------------------------------------------
227
228
SUMOEmissionClass
229
PollutantsInterface::getClassByName(const std::string& eClass, const SUMOVehicleClass vc) {
230
const std::string::size_type sep = eClass.find("/");
231
const std::string model = eClass.substr(0, sep); // this includes the case of no separator
232
for (int i = 0; i < 8; i++) {
233
if (myHelpers[i]->getName() == model) {
234
if (sep != std::string::npos) {
235
const std::string subClass = eClass.substr(sep + 1);
236
if (subClass == "zero") {
237
return myZeroHelper.getClassByName("default", vc);
238
}
239
return myHelpers[i]->getClassByName(subClass, vc);
240
}
241
return myHelpers[i]->getClassByName("default", vc);
242
}
243
}
244
if (sep == std::string::npos) {
245
if (eClass == "zero") {
246
return myZeroHelper.getClassByName("default", vc);
247
}
248
WRITE_WARNINGF("Emission classes should always use the model as a prefix, please recheck '%'. Starting with SUMO 1.24 this will be an error.", eClass)
249
// default HBEFA2
250
return myHBEFA2Helper.getClassByName(eClass, vc);
251
}
252
throw InvalidArgument("Unknown emission class '" + eClass + "'.");
253
}
254
255
256
const std::vector<SUMOEmissionClass>
257
PollutantsInterface::getAllClasses() {
258
std::vector<SUMOEmissionClass> result;
259
for (int i = 0; i < 8; i++) {
260
myHelpers[i]->addAllClassesInto(result);
261
}
262
return result;
263
}
264
265
266
const std::vector<std::string>&
267
PollutantsInterface::getAllClassesStr() {
268
// first check if myAllClassesStr has to be filled
269
if (myAllClassesStr.empty()) {
270
// first obtain all emissionClasses
271
std::vector<SUMOEmissionClass> emissionClasses;
272
for (int i = 0; i < 8; i++) {
273
myHelpers[i]->addAllClassesInto(emissionClasses);
274
}
275
// now write all emissionClasses in myAllClassesStr
276
for (const auto& i : emissionClasses) {
277
myAllClassesStr.push_back(getName(i));
278
}
279
}
280
return myAllClassesStr;
281
}
282
283
std::string
284
PollutantsInterface::getName(const SUMOEmissionClass c) {
285
return myHelpers[c >> 16]->getClassName(c);
286
}
287
288
289
std::string
290
PollutantsInterface::getPollutantName(const EmissionType e) {
291
switch (e) {
292
case CO2:
293
return "CO2";
294
case CO:
295
return "CO";
296
case HC:
297
return "HC";
298
case FUEL:
299
return "fuel";
300
case NO_X:
301
return "NOx";
302
case PM_X:
303
return "PMx";
304
case ELEC:
305
return "electricity";
306
default:
307
throw InvalidArgument("Unknown emission type '" + toString(e) + "'");
308
}
309
}
310
311
bool
312
PollutantsInterface::isHeavy(const SUMOEmissionClass c) {
313
return (c & HEAVY_BIT) != 0;
314
}
315
316
317
bool
318
PollutantsInterface::isSilent(const SUMOEmissionClass c) {
319
return myHelpers[c >> 16]->isSilent(c);
320
}
321
322
323
SUMOEmissionClass
324
PollutantsInterface::getClass(const SUMOEmissionClass base, const std::string& vClass,
325
const std::string& fuel, const std::string& eClass, const double weight) {
326
return myHelpers[base >> 16]->getClass(base, vClass, fuel, eClass, weight);
327
}
328
329
330
std::string
331
PollutantsInterface::getAmitranVehicleClass(const SUMOEmissionClass c) {
332
return myHelpers[c >> 16]->getAmitranVehicleClass(c);
333
}
334
335
336
std::string
337
PollutantsInterface::getFuel(const SUMOEmissionClass c) {
338
return myHelpers[c >> 16]->getFuel(c);
339
}
340
341
342
int
343
PollutantsInterface::getEuroClass(const SUMOEmissionClass c) {
344
return myHelpers[c >> 16]->getEuroClass(c);
345
}
346
347
348
double
349
PollutantsInterface::getWeight(const SUMOEmissionClass c) {
350
return myHelpers[c >> 16]->getWeight(c);
351
}
352
353
354
double
355
PollutantsInterface::compute(const SUMOEmissionClass c, const EmissionType e, const double v, const double a, const double slope, const EnergyParams* param) {
356
return myHelpers[c >> 16]->compute(c, e, v, a, slope, param);
357
}
358
359
360
PollutantsInterface::Emissions
361
PollutantsInterface::computeAll(const SUMOEmissionClass c, const double v, const double a, const double slope, const EnergyParams* param) {
362
const Helper* const h = myHelpers[c >> 16];
363
return Emissions(h->compute(c, CO2, v, a, slope, param), h->compute(c, CO, v, a, slope, param), h->compute(c, HC, v, a, slope, param),
364
h->compute(c, FUEL, v, a, slope, param), h->compute(c, NO_X, v, a, slope, param), h->compute(c, PM_X, v, a, slope, param),
365
h->compute(c, ELEC, v, a, slope, param));
366
}
367
368
369
double
370
PollutantsInterface::computeDefault(const SUMOEmissionClass c, const EmissionType e, const double v, const double a, const double slope, const double tt, const EnergyParams* param) {
371
const Helper* const h = myHelpers[c >> 16];
372
return (h->compute(c, e, v, 0, slope, param) + h->compute(c, e, v - a, a, slope, param)) * tt / 2.;
373
}
374
375
376
double
377
PollutantsInterface::getModifiedAccel(const SUMOEmissionClass c, const double v, const double a, const double slope, const EnergyParams* param) {
378
return myHelpers[c >> 16]->getModifiedAccel(c, v, a, slope, param);
379
}
380
381
382
double
383
PollutantsInterface::getCoastingDecel(const SUMOEmissionClass c, const double v, const double a, const double slope, const EnergyParams* param) {
384
return myHelpers[c >> 16]->getCoastingDecel(c, v, a, slope, param);
385
}
386
387
388
const HelpersEnergy&
389
PollutantsInterface::getEnergyHelper() {
390
return myEnergyHelper;
391
}
392
393
/****************************************************************************/
394
395