Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
PHEMCEP.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/****************************************************************************/
22// Helper class for PHEM Light, holds a specific CEP for a PHEM emission class
23/****************************************************************************/
24#include <config.h>
25
26#include <cmath>
27#include <string>
31#include "PHEMCEP.h"
32
33
34// ===========================================================================
35// method definitions
36// ===========================================================================
37PHEMCEP::PHEMCEP(bool heavyVehicle, SUMOEmissionClass emissionClass, const std::string& emissionClassIdentifier,
38 double vehicleMass, double vehicleLoading, double vehicleMassRot,
39 double crossArea, double cdValue,
40 double f0, double f1, double f2, double f3, double f4,
41 double ratedPower, double pNormV0, double pNormP0, double pNormV1, double pNormP1,
42 double axleRatio, double engineIdlingSpeed, double engineRatedSpeed, double effectiveWheelDiameter,
43 double idlingFC,
44 const std::string& vehicleFuelType,
45 const std::vector< std::vector<double> >& matrixFC,
46 const std::vector<std::string>& headerLinePollutants,
47 const std::vector< std::vector<double> >& matrixPollutants,
48 const std::vector< std::vector<double> >& matrixSpeedRotational,
49 const std::vector< std::vector<double> >& normedDragTable,
50 const std::vector<double>& idlingValuesPollutants) {
51 _emissionClass = emissionClass;
52 _resistanceF0 = f0;
53 _resistanceF1 = f1;
54 _resistanceF2 = f2;
55 _resistanceF3 = f3;
56 _resistanceF4 = f4;
57 _cdValue = cdValue;
58 _crossSectionalArea = crossArea;
59 _massVehicle = vehicleMass;
60 _vehicleLoading = vehicleLoading;
61 _massRot = vehicleMassRot;
62 _ratedPower = ratedPower;
63 _vehicleFuelType = vehicleFuelType;
64
65 _pNormV0 = pNormV0 / 3.6;
66 _pNormP0 = pNormP0;
67 _pNormV1 = pNormV1 / 3.6;
68 _pNormP1 = pNormP1;
69
70 _axleRatio = axleRatio;
71 _engineIdlingSpeed = engineIdlingSpeed;
72 _engineRatedSpeed = engineRatedSpeed;
73 _effictiveWheelDiameter = effectiveWheelDiameter;
74
75 _heavyVehicle = heavyVehicle;
76 _idlingFC = idlingFC;
77
78 std::vector<std::string> pollutantIdentifier;
79 std::vector< std::vector<double> > pollutantMeasures;
80 std::vector<std::vector<double> > normalizedPollutantMeasures;
81
82 // init pollutant identifiers
83 for (int i = 0; i < (int)headerLinePollutants.size(); i++) {
84 pollutantIdentifier.push_back(headerLinePollutants[i]);
85 } // end for
86
87 // get size of powerPatterns
88 _sizeOfPatternFC = (int)matrixFC.size();
89 _sizeOfPatternPollutants = (int)matrixPollutants.size();
90
91 // initialize measures
92 for (int i = 0; i < (int)headerLinePollutants.size(); i++) {
93 pollutantMeasures.push_back(std::vector<double>());
94 normalizedPollutantMeasures.push_back(std::vector<double>());
95 } // end for
96
97 // looping through matrix and assigning values for speed rotational table
101 for (int i = 0; i < (int)matrixSpeedRotational.size(); i++) {
102 if (matrixSpeedRotational[i].size() != 3) {
103 throw InvalidArgument("Error loading vehicle file for: " + emissionClassIdentifier);
104 }
105
106 _speedPatternRotational.push_back(matrixSpeedRotational[i][0] / 3.6);
107 _speedCurveRotational.push_back(matrixSpeedRotational[i][1]);
108 _gearTransmissionCurve.push_back(matrixSpeedRotational[i][2]);
109 } // end for
110
111 // looping through matrix and assigning values for drag table
112 _nNormTable.clear();
113 _dragNormTable.clear();
114 for (int i = 0; i < (int) normedDragTable.size(); i++) {
115 if (normedDragTable[i].size() != 2) {
116 return;
117 }
118
119 _nNormTable.push_back(normedDragTable[i][0]);
120 _dragNormTable.push_back(normedDragTable[i][1]);
121
122 } // end for
123
124 // looping through matrix and assigning values for Fuel consumption
125 _cepCurveFC.clear();
126 _powerPatternFC.clear();
128 _normedCepCurveFC.clear();
129 for (int i = 0; i < (int)matrixFC.size(); i++) {
130 if (matrixFC[i].size() != 2) {
131 throw InvalidArgument("Error loading vehicle file for: " + emissionClassIdentifier);
132 }
133
134 _powerPatternFC.push_back(matrixFC[i][0] * _ratedPower);
135 _normalizedPowerPatternFC.push_back(matrixFC[i][0]);
136 _cepCurveFC.push_back(matrixFC[i][1] * _ratedPower);
137 _normedCepCurveFC.push_back(matrixFC[i][1]);
138
139 } // end for
140
142 double pollutantMultiplyer = 1;
143
145
146 // looping through matrix and assigning values for pollutants
147
148 if (heavyVehicle) {
150 pollutantMultiplyer = _ratedPower;
152 } else {
155 } // end if
156
157 const int headerCount = (int)headerLinePollutants.size();
158 for (int i = 0; i < (int)matrixPollutants.size(); i++) {
159 for (int j = 0; j < (int)matrixPollutants[i].size(); j++) {
160 if ((int)matrixPollutants[i].size() != headerCount + 1) {
161 return;
162 }
163
164 if (j == 0) {
165 _normailzedPowerPatternPollutants.push_back(matrixPollutants[i][j]);
166 _powerPatternPollutants.push_back(matrixPollutants[i][j] * _normalizingPower);
167 } else {
168 pollutantMeasures[j - 1].push_back(matrixPollutants[i][j] * pollutantMultiplyer);
169 normalizedPollutantMeasures[j - 1].push_back(matrixPollutants[i][j]);
170 } // end if
171 } // end for
172 } // end for
173
174 for (int i = 0; i < (int) headerLinePollutants.size(); i++) {
175 _cepCurvePollutants.insert(pollutantIdentifier[i], pollutantMeasures[i]);
176 _normalizedCepCurvePollutants.insert(pollutantIdentifier[i], normalizedPollutantMeasures[i]);
177 _idlingValuesPollutants.insert(pollutantIdentifier[i], idlingValuesPollutants[i] * pollutantMultiplyer);
178 } // end for
179
180 _idlingFC = idlingFC * _ratedPower;
181
182} // end of Cep
183
184
186 // free power pattern
187 _powerPatternFC.clear();
189 _cepCurveFC.clear();
190 _speedCurveRotational.clear();
192} // end of ~Cep
193
194
195double
196PHEMCEP::GetEmission(const std::string& pollutant, double power, double speed, bool normalized) const {
197 std::vector<double> emissionCurve;
198 std::vector<double> powerPattern;
199
200 if (!normalized && fabs(speed) <= ZERO_SPEED_ACCURACY) {
201 if (pollutant == "FC") {
202 return _idlingFC;
203 } else {
204 return _idlingValuesPollutants.get(pollutant);
205 }
206 } // end if
207
208 if (pollutant == "FC") {
209 if (normalized) {
210 emissionCurve = _normedCepCurveFC;
211 powerPattern = _normalizedPowerPatternFC;
212 } else {
213 emissionCurve = _cepCurveFC;
214 powerPattern = _powerPatternFC;
215 }
216 } else {
217 if (!_cepCurvePollutants.hasString(pollutant)) {
218 throw InvalidArgument("Emission pollutant " + pollutant + " not found!");
219 }
220
221 if (normalized) {
222 emissionCurve = _normalizedCepCurvePollutants.get(pollutant);
224 } else {
225 emissionCurve = _cepCurvePollutants.get(pollutant);
226 powerPattern = _powerPatternPollutants;
227 }
228
229 } // end if
230
231
232
233 if (emissionCurve.size() == 0) {
234 throw InvalidArgument("Empty emission curve for " + pollutant + " found!");
235 }
236
237 if (emissionCurve.size() == 1) {
238 return emissionCurve[0];
239 }
240
241 // in case that the demanded power is smaller than the first entry (smallest) in the power pattern the first two entries are extrapolated
242 if (power <= powerPattern.front()) {
243 double calcEmission = PHEMCEP::Interpolate(power, powerPattern[0], powerPattern[1], emissionCurve[0], emissionCurve[1]);
244
245 if (calcEmission < 0) {
246 return 0;
247 } else {
248 return calcEmission;
249 }
250
251 } // end if
252
253 // if power bigger than all entries in power pattern the last two values are linearly extrapolated
254 if (power >= powerPattern.back()) {
255 return PHEMCEP::Interpolate(power, powerPattern[powerPattern.size() - 2], powerPattern.back(), emissionCurve[emissionCurve.size() - 2], emissionCurve.back());
256 } // end if
257
258 // bisection search to find correct position in power pattern
259 int upperIndex;
260 int lowerIndex;
261
262 PHEMCEP::FindLowerUpperInPattern(lowerIndex, upperIndex, powerPattern, power);
263
264 return PHEMCEP::Interpolate(power, powerPattern[lowerIndex], powerPattern[upperIndex], emissionCurve[lowerIndex], emissionCurve[upperIndex]);
265
266} // end of GetEmission
267
268
269double
270PHEMCEP::Interpolate(double px, double p1, double p2, double e1, double e2) const {
271 if (p2 == p1) {
272 return e1;
273 }
274 return e1 + (px - p1) / (p2 - p1) * (e2 - e1);
275} // end of Interpolate
276
277
278double PHEMCEP::GetDecelCoast(double speed, double acc, double gradient, double /* vehicleLoading */) const {
279 if (speed < SPEED_DCEL_MIN) {
280 return speed / SPEED_DCEL_MIN * GetDecelCoast(SPEED_DCEL_MIN, acc, gradient, _vehicleLoading); // !!!vehicleLoading
281 } // end if
282
283 double rotCoeff = GetRotationalCoeffecient(speed);
284
285 int upperIndex;
286 int lowerIndex;
287
288 double iGear = GetGearCoeffecient(speed);
289
290 double iTot = iGear * _axleRatio;
291
292 double n = (30 * speed * iTot) / ((_effictiveWheelDiameter / 2) * M_PI2);
294
295 FindLowerUpperInPattern(lowerIndex, upperIndex, _nNormTable, nNorm);
296
297 double fMot = 0;
298
299 if (speed >= 10e-2) {
300 fMot = (-GetDragCoeffecient(nNorm) * _ratedPower * 1000 / speed) / 0.9;
301 } // end if
302
303 double fRoll = (_resistanceF0
304 + _resistanceF1 * speed
305 + pow(_resistanceF2 * speed, 2)
306 + pow(_resistanceF3 * speed, 3)
307 + pow(_resistanceF4 * speed, 4)) * (_massVehicle + _vehicleLoading) * GRAVITY_CONST; // !!!vehicleLoading
308
309 double fAir = _cdValue * _crossSectionalArea * 1.2 * 0.5 * pow(speed, 2);
310
311 double fGrad = (_massVehicle + _vehicleLoading) * GRAVITY_CONST * gradient / 100; // !!!vehicleLoading
312
313 return -(fMot + fRoll + fAir + fGrad) / ((_massVehicle + _vehicleLoading) * rotCoeff); // !!!vehicleLoading
314} // end of GetDecelCoast
315
316
317double
319 int upperIndex;
320 int lowerIndex;
321
322 PHEMCEP::FindLowerUpperInPattern(lowerIndex, upperIndex, _speedPatternRotational, speed);
323
324 return PHEMCEP::Interpolate(speed,
325 _speedPatternRotational[lowerIndex],
326 _speedPatternRotational[upperIndex],
327 _speedCurveRotational[lowerIndex],
328 _speedCurveRotational[upperIndex]);
329} // end of GetRotationalCoeffecient
330
331double PHEMCEP::GetGearCoeffecient(double speed) const {
332 int upperIndex;
333 int lowerIndex;
334
335 FindLowerUpperInPattern(lowerIndex, upperIndex, _gearTransmissionCurve, speed);
336
337 return Interpolate(speed,
338 _speedPatternRotational[lowerIndex],
339 _speedPatternRotational[upperIndex],
340 _gearTransmissionCurve[lowerIndex],
341 _gearTransmissionCurve[upperIndex]);
342} // end of GetGearCoefficient
343
344double PHEMCEP::GetDragCoeffecient(double nNorm) const {
345 int upperIndex;
346 int lowerIndex;
347
348 FindLowerUpperInPattern(lowerIndex, upperIndex, _dragNormTable, nNorm);
349
350 return Interpolate(nNorm,
351 _nNormTable[lowerIndex],
352 _nNormTable[upperIndex],
353 _dragNormTable[lowerIndex],
354 _dragNormTable[upperIndex]);
355} // end of GetGearCoefficient
356
357void PHEMCEP::FindLowerUpperInPattern(int& lowerIndex, int& upperIndex, const std::vector<double>& pattern, double value) const {
358 if (value <= pattern.front()) {
359 lowerIndex = 0;
360 upperIndex = 0;
361 return;
362
363 } // end if
364
365 if (value >= pattern.back()) {
366 lowerIndex = (int)pattern.size() - 1;
367 upperIndex = (int)pattern.size() - 1;
368 return;
369 } // end if
370
371 // bisection search to find correct position in power pattern
372 int middleIndex = ((int)pattern.size() - 1) / 2;
373 upperIndex = (int)pattern.size() - 1;
374 lowerIndex = 0;
375
376 while (upperIndex - lowerIndex > 1) {
377 if (pattern[middleIndex] == value) {
378 lowerIndex = middleIndex;
379 upperIndex = middleIndex;
380 return;
381 } else if (pattern[middleIndex] < value) {
382 lowerIndex = middleIndex;
383 middleIndex = (upperIndex - lowerIndex) / 2 + lowerIndex;
384 } else {
385 upperIndex = middleIndex;
386 middleIndex = (upperIndex - lowerIndex) / 2 + lowerIndex;
387 } // end if
388 } // end while
389
390 if (pattern[lowerIndex] <= value && value < pattern[upperIndex]) {
391 return;
392 } else {
393 throw ProcessError("Error during calculation of position in pattern!");
394 }
395} // end of FindLowerUpperInPattern
396
397
398double
399PHEMCEP::CalcPower(double v, double a, double slope, double /* vehicleLoading */) const {
400 const double rotFactor = GetRotationalCoeffecient(v);
401 double power = (_massVehicle + _vehicleLoading) * GRAVITY_CONST * (_resistanceF0 + _resistanceF1 * v + _resistanceF4 * pow(v, 4)) * v;
402 power += (_crossSectionalArea * _cdValue * AIR_DENSITY_CONST / 2) * pow(v, 3);
403 power += (_massVehicle * rotFactor + _massRot + _vehicleLoading) * a * v;
404 power += (_massVehicle + _vehicleLoading) * slope * 0.01 * v;
405 return power / 950.;
406}
407
408
409double
410PHEMCEP::GetMaxAccel(double v, double a, double gradient, double /* vehicleLoading */) const {
412 double rotFactor = GetRotationalCoeffecient(v);
413 const double pMaxForAcc = GetPMaxNorm(v) * _ratedPower - PHEMCEP::CalcPower(v, 0, gradient, _vehicleLoading); // !!!vehicleLoading
414 return (pMaxForAcc * 1000) / ((_massVehicle * rotFactor + _massRot + _vehicleLoading) * v); // !!!vehicleLoading
415}
416
417
418
419double PHEMCEP::GetPMaxNorm(double speed) const {
420 // Linear function between v0 and v1, constant elsewhere
421 if (speed <= _pNormV0) {
422 return _pNormP0;
423 } else if (speed >= _pNormV1) {
424 return _pNormP1;
425 } else {
427 }
428} // end of GetPMaxNorm
429
430
431/****************************************************************************/
@ RatedPower
Definition PHEMCEP.h:37
@ DrivingPower
Definition PHEMCEP.h:38
const double M_PI2
const double AIR_DENSITY_CONST
const double ZERO_SPEED_ACCURACY
const double SPEED_DCEL_MIN
const double GRAVITY_CONST
const double NORMALIZING_ACCELARATION
const double NORMALIZING_SPEED
int SUMOEmissionClass
#define UNUSED_PARAMETER(x)
Definition StdDefs.h:30
double _resistanceF3
Rolling resistance f3.
Definition PHEMCEP.h:266
double _pNormV0
Step functions parameter for maximum rated power.
Definition PHEMCEP.h:282
void FindLowerUpperInPattern(int &lowerIndex, int &upperIndex, const std::vector< double > &pattern, double value) const
Finds bounding upper and lower index in pattern for value.
Definition PHEMCEP.cpp:357
double _effictiveWheelDiameter
Definition PHEMCEP.h:292
double _idlingFC
Definition PHEMCEP.h:293
std::vector< double > _speedCurveRotational
Definition PHEMCEP.h:312
StringBijection< std::vector< double > > _cepCurvePollutants
Definition PHEMCEP.h:316
double _vehicleLoading
vehicle loading
Definition PHEMCEP.h:276
int _sizeOfPatternFC
Definition PHEMCEP.h:295
std::string _vehicleFuelType
Definition PHEMCEP.h:294
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
double GetDragCoeffecient(double nNorm) const
Definition PHEMCEP.cpp:344
double _pNormV1
Step functions parameter for maximum rated power.
Definition PHEMCEP.h:286
double _pNormP1
Step functions parameter for maximum rated power.
Definition PHEMCEP.h:288
double _resistanceF2
Rolling resistance f2.
Definition PHEMCEP.h:264
std::vector< double > _nNormTable
Definition PHEMCEP.h:314
double _engineIdlingSpeed
Definition PHEMCEP.h:290
double _resistanceF4
Rolling resistance f4.
Definition PHEMCEP.h:268
double _resistanceF1
Rolling resistance f1.
Definition PHEMCEP.h:262
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
double _resistanceF0
Rolling resistance f0.
Definition PHEMCEP.h:260
std::vector< double > _normedCepCurveFC
Definition PHEMCEP.h:311
std::vector< double > _cepCurveFC
Definition PHEMCEP.h:309
double GetDecelCoast(double speed, double acc, double gradient, double vehicleLoading) const
Definition PHEMCEP.cpp:278
std::vector< double > _powerPatternPollutants
Definition PHEMCEP.h:305
std::vector< double > _normailzedPowerPatternPollutants
Definition PHEMCEP.h:307
double _massVehicle
vehicle mass
Definition PHEMCEP.h:274
double _axleRatio
Definition PHEMCEP.h:289
~PHEMCEP()
Destructor.
Definition PHEMCEP.cpp:185
double _pNormP0
Step functions parameter for maximum rated power.
Definition PHEMCEP.h:284
double _drivingPower
Definition PHEMCEP.h:299
SUMOEmissionClass _emissionClass
PHEM emission class of vehicle.
Definition PHEMCEP.h:257
double GetMaxAccel(double v, double a, double gradient, double vehicleLoading=0) const
Returns the maximum accelaration for a vehicle at state v,a, slope and loading.
Definition PHEMCEP.cpp:410
std::vector< double > _dragNormTable
Definition PHEMCEP.h:315
NormalizingType _normalizingType
Definition PHEMCEP.h:258
std::vector< double > _speedPatternRotational
Definition PHEMCEP.h:301
double Interpolate(double px, double p1, double p2, double e1, double e2) const
Interpolates emission linearly between two known power-emission pairs.
Definition PHEMCEP.cpp:270
std::vector< double > _powerPatternFC
Definition PHEMCEP.h:303
StringBijection< double > _idlingValuesPollutants
Definition PHEMCEP.h:318
double GetRotationalCoeffecient(double speed) const
Calculates rotational index for speed.
Definition PHEMCEP.cpp:318
int _sizeOfPatternPollutants
Definition PHEMCEP.h:297
double GetGearCoeffecient(double speed) const
Definition PHEMCEP.cpp:331
double _ratedPower
rated power of vehicle
Definition PHEMCEP.h:280
double _massRot
rotational mass of vehicle
Definition PHEMCEP.h:278
std::vector< double > _gearTransmissionCurve
Definition PHEMCEP.h:313
double _normalizingPower
Definition PHEMCEP.h:298
StringBijection< std::vector< double > > _normalizedCepCurvePollutants
Definition PHEMCEP.h:317
double GetPMaxNorm(double speed) const
Calculates maximum available rated power for speed.
Definition PHEMCEP.cpp:419
std::vector< double > _normalizedPowerPatternFC
Definition PHEMCEP.h:306
PHEMCEP(bool heavyVehicel, SUMOEmissionClass emissionClass, const std::string &emissionClassIdentifier, double vehicleMass, double vehicleLoading, double vehicleMassRot, double crossArea, double cdValue, double f0, double f1, double f2, double f3, double f4, double ratedPower, double pNormV0, double pNormP0, double pNormV1, double pNormP1, double axleRatio, double engineIdlingSpeed, double engineRatedSpeed, double effectiveWheelDiameter, double idlingFC, const std::string &vehicleFuelType, const std::vector< std::vector< double > > &matrixFC, const std::vector< std::string > &headerLinePollutants, const std::vector< std::vector< double > > &matrixPollutants, const std::vector< std::vector< double > > &matrixSpeedRotational, const std::vector< std::vector< double > > &normedDragTable, const std::vector< double > &idlingValuesPollutants)
Definition PHEMCEP.cpp:37
double _crossSectionalArea
crosssectional area of vehicle
Definition PHEMCEP.h:272
double _cdValue
Cw value.
Definition PHEMCEP.h:270
bool _heavyVehicle
Definition PHEMCEP.h:300
double _engineRatedSpeed
Definition PHEMCEP.h:291
bool hasString(const std::string &str) const
T get(const std::string &str) const
void insert(const std::string str, const T key, bool checkDuplicates=true)