Eclipse SUMO - Simulation of Urban MObility
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>
28 #include <utils/common/StdDefs.h>
31 #include "PHEMCEP.h"
32 
33 
34 // ===========================================================================
35 // method definitions
36 // ===========================================================================
37 PHEMCEP::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
98  _speedCurveRotational.clear();
100  _gearTransmissionCurve.clear();
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 
141  _powerPatternPollutants.clear();
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();
188  _powerPatternPollutants.clear();
189  _cepCurveFC.clear();
190  _speedCurveRotational.clear();
191  _speedPatternRotational.clear();
192 } // end of ~Cep
193 
194 
195 double
196 PHEMCEP::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);
223  powerPattern = _normailzedPowerPatternPollutants;
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 
269 double
270 PHEMCEP::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 
278 double 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);
293  double nNorm = (n - _engineIdlingSpeed) / (_engineRatedSpeed - _engineIdlingSpeed);
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 
317 double
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 
331 double 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 
344 double 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 
357 void 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 
398 double
399 PHEMCEP::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 
409 double
410 PHEMCEP::GetMaxAccel(double v, double a, double gradient, double /* vehicleLoading */) const {
411  UNUSED_PARAMETER(a);
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 
419 double 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
Definition: PHEMConstants.h:33
const double AIR_DENSITY_CONST
Definition: PHEMConstants.h:26
const double ZERO_SPEED_ACCURACY
Definition: PHEMConstants.h:34
const double SPEED_DCEL_MIN
Definition: PHEMConstants.h:32
const double GRAVITY_CONST
Definition: PHEMConstants.h:25
const double NORMALIZING_ACCELARATION
Definition: PHEMConstants.h:29
const double NORMALIZING_SPEED
Definition: PHEMConstants.h:28
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)