Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
V5/cpp/CEP.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2016-2024 German Aerospace Center (DLR) and others.
4// PHEMlight module
5// Copyright (C) 2016-2023 Technische Universitaet Graz, https://www.tugraz.at/
6// This program and the accompanying materials are made available under the
7// terms of the Eclipse Public License 2.0 which is available at
8// https://www.eclipse.org/legal/epl-2.0/
9// This Source Code may also be made available under the following Secondary
10// Licenses when the conditions for such availability set forth in the Eclipse
11// Public License 2.0 are satisfied: GNU General Public License, version 2
12// or later which is available at
13// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
14// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
15/****************************************************************************/
21//
22/****************************************************************************/
23#include <config.h>
24
25#include "CEP.h"
26#include "CEPHandler.h"
27#include "Constants.h"
28#include "Helpers.h"
29
30
31namespace PHEMlightdllV5 {
32
33 CEP::CEP(VEHPHEMLightJSON::VEH* Vehicle, std::vector<std::string>& headerLineFCvalues, std::vector<std::vector<double> >& matrixFCvalues, std::vector<std::string>& headerLinePollutants, std::vector<std::vector<double> >& matrixPollutants, std::vector<double>& idlingFCvalues, std::vector<double>& idlingPollutants) {
35 _resistanceF0 = Vehicle->getRollingResData()->getFr0();
36 _resistanceF1 = Vehicle->getRollingResData()->getFr1();
37 _resistanceF2 = Vehicle->getRollingResData()->getFr2();
38 _resistanceF3 = Vehicle->getRollingResData()->getFr3();
39 _resistanceF4 = Vehicle->getRollingResData()->getFr4();
40 _cWValue = Vehicle->getVehicleData()->getCw();
41 _crossSectionalArea = Vehicle->getVehicleData()->getA();
42 _massVehicle = Vehicle->getVehicleData()->getMass();
43 _vehicleLoading = Vehicle->getVehicleData()->getLoading();
44 _vehicleMassRot = Vehicle->getVehicleData()->getRedMassWheel();
45 setCalcType(Vehicle->getVehicleData()->getCalcType());
46//C# TO C++ CONVERTER NOTE: The following 'switch' operated on a string variable and was converted to C++ 'if-else' logic:
47// switch (CalcType)
48//ORIGINAL LINE: case "Conv":
49 if (getCalcType() == "Conv") {
50 setRatedPower(Vehicle->getEngineData()->getICEData()->getPrated());
51 _engineRatedSpeed = Vehicle->getEngineData()->getICEData()->getnrated();
52 _engineIdlingSpeed = Vehicle->getEngineData()->getICEData()->getIdling();
53 }
54//ORIGINAL LINE: case "HEV":
55 else if (getCalcType() == "HEV") {
56 // Power von beiden zusammen Rest bezogen auf ICE
57 setRatedPower(Vehicle->getEngineData()->getICEData()->getPrated() + Vehicle->getEngineData()->getEMData()->getPrated());
58 _engineRatedSpeed = Vehicle->getEngineData()->getICEData()->getnrated();
59 _engineIdlingSpeed = Vehicle->getEngineData()->getICEData()->getIdling();
60 }
61//ORIGINAL LINE: case "BEV":
62 else if (getCalcType() == "BEV") {
63 setRatedPower(Vehicle->getEngineData()->getEMData()->getPrated());
64 _engineRatedSpeed = Vehicle->getEngineData()->getEMData()->getnrated();
66 }
67
68 _effectiveWheelDiameter = Vehicle->getVehicleData()->getWheelDiameter();
69 privateHeavyVehicle = Vehicle->getVehicleData()->getMassType() == Constants::HeavyVehicle;
70 setFuelType(Vehicle->getVehicleData()->getFuelType());
71 _axleRatio = Vehicle->getTransmissionData()->getAxelRatio();
72 _auxPower = Vehicle->getAuxiliariesData()->getPauxnorm();
73
74 _pNormV0 = Vehicle->getFLDData()->getP_n_max_v0() / 3.6;
75 _pNormP0 = Vehicle->getFLDData()->getP_n_max_p0();
76 _pNormV1 = Vehicle->getFLDData()->getP_n_max_v1() / 3.6;
77 _pNormP1 = Vehicle->getFLDData()->getP_n_max_p1();
78
79 // Init pollutant identifiers, unit and measures
80 std::vector<std::string> FCvaluesIdentifier;
81 std::vector<std::vector<double> > normalizedFCvaluesMeasures;
82 for (int i = 0; i < (int)headerLineFCvalues.size(); i++) {
83 FCvaluesIdentifier.push_back(headerLineFCvalues[i]);
84 normalizedFCvaluesMeasures.push_back(std::vector<double>());
85 }
86
87 // Init pollutant identifiers, unit and measures
88 std::vector<std::string> pollutantIdentifier;
89 std::vector<std::vector<double> > normalizedPollutantMeasures;
90 for (int i = 0; i < (int)headerLinePollutants.size(); i++) {
91 pollutantIdentifier.push_back(headerLinePollutants[i]);
92 normalizedPollutantMeasures.push_back(std::vector<double>());
93 }
94
95 // Assigning values for speed rotational table
96 _speedPatternRotational = std::vector<double>();
97 for (int i = 0; i < (int)Vehicle->getTransmissionData()->getTransm()["Speed"].size(); i++) {
98 _speedPatternRotational.push_back(Vehicle->getTransmissionData()->getTransm()["Speed"][i] / 3.6);
99 }
100
101 _gearTransmissionCurve = Vehicle->getTransmissionData()->getTransm()["GearRatio"];
102 _speedCurveRotational = Vehicle->getTransmissionData()->getTransm()["RotMassF"];
103
104 // Assigning values for drag table
105 _nNormTable = Vehicle->getFLDData()->getDragCurve()["n_norm"];
106 _dragNormTable = Vehicle->getFLDData()->getDragCurve()["pe_drag_norm"];
107
108 // Looping through matrix and assigning values for FC values
109 _normalizedPowerPatternFCvalues = std::vector<double>();
110
111 int headerFCCount = (int)headerLineFCvalues.size();
112 for (int i = 0; i < (int)matrixFCvalues.size(); i++) {
113 for (int j = 0; j < (int)matrixFCvalues[i].size(); j++) {
114 if ((int)matrixFCvalues[i].size() != headerFCCount + 1) {
115 return;
116 }
117
118 if (j == 0) {
119 _normalizedPowerPatternFCvalues.push_back(matrixFCvalues[i][j]);
120 }
121 else {
122 normalizedFCvaluesMeasures[j - 1].push_back(matrixFCvalues[i][j]);
123 }
124 }
125 }
126
127 _idlingValueFCvalues = std::map<std::string, double>();
128 _normedCepCurveFCvalues = std::map<std::string, std::vector<double> >();
129
130 for (int i = 0; i < (int)headerLineFCvalues.size(); i++) {
131 _normedCepCurveFCvalues.insert(std::make_pair(FCvaluesIdentifier[i], normalizedFCvaluesMeasures[i]));
132 _idlingValueFCvalues.insert(std::make_pair(FCvaluesIdentifier[i], idlingFCvalues[i]));
133 }
134
135 _normalizedPowerPatternPollutants = std::vector<double>();
136 _cepNormalizedCurvePollutants = std::map<std::string, std::vector<double> >();
137
138 int headerCount = (int)headerLinePollutants.size();
139 for (int i = 0; i < (int)matrixPollutants.size(); i++) {
140 for (int j = 0; j < (int)matrixPollutants[i].size(); j++) {
141 if ((int)matrixPollutants[i].size() != headerCount + 1) {
142 return;
143 }
144
145 if (j == 0) {
146 _normalizedPowerPatternPollutants.push_back(matrixPollutants[i][j]);
147 }
148 else {
149 normalizedPollutantMeasures[j - 1].push_back(matrixPollutants[i][j]);
150 }
151 }
152 }
153
154 _idlingValuesPollutants = std::map<std::string, double>();
155
156 for (int i = 0; i < (int)headerLinePollutants.size(); i++) {
157 _cepNormalizedCurvePollutants.insert(std::make_pair(pollutantIdentifier[i], normalizedPollutantMeasures[i]));
158 _idlingValuesPollutants.insert(std::make_pair(pollutantIdentifier[i], idlingPollutants[i]));
159 }
160
161 _FleetMix = std::map<std::string, double>();
162 _FleetMix.insert(std::make_pair(Constants::strGasoline, 0));
163 _FleetMix.insert(std::make_pair(Constants::strDiesel, 0));
164 _FleetMix.insert(std::make_pair(Constants::strCNG, 0));
165 _FleetMix.insert(std::make_pair(Constants::strLPG, 0));
166 }
167
168 const bool& CEP::getHeavyVehicle() const {
169 return privateHeavyVehicle;
170 }
171
172 const std::string& CEP::getFuelType() const {
173 return privateFuelType;
174 }
175
176 void CEP::setFuelType(const std::string& value) {
177 privateFuelType = value;
178 }
179
180 const std::string& CEP::getCalcType() const {
181 return privateCalcType;
182 }
183
184 void CEP::setCalcType(const std::string& value) {
185 privateCalcType = value;
186 }
187
188 const double& CEP::getRatedPower() const {
189 return privateRatedPower;
190 }
191
192 void CEP::setRatedPower(const double& value) {
193 privateRatedPower = value;
194 }
195
196 double CEP::CalcEngPower(double power, const double ratedPower) {
197 if (power < _normalizedPowerPatternFCvalues.front() * ratedPower) {
198 return _normalizedPowerPatternFCvalues.front() * ratedPower;
199 }
200 if (power > _normalizedPowerPatternFCvalues.back() * ratedPower) {
201 return _normalizedPowerPatternFCvalues.back() * ratedPower;
202 }
203
204 return power;
205 }
206
207 double CEP::GetEmission(const std::string& pollutant, double power, double speed, Helpers* VehicleClass, const double drivingPower, const double ratedPower) {
208 //Declaration
209 std::vector<double>* emissionCurve = nullptr;
210 std::vector<double>* powerPattern = nullptr;
211
212 // bisection search to find correct position in power pattern
213 int upperIndex;
214 int lowerIndex;
215
216 double emissionMultiplier = getHeavyVehicle() ? ratedPower : 1.;
217 if (std::abs(speed) <= Constants::ZERO_SPEED_ACCURACY) {
219 VehicleClass->setErrMsg(std::string("Emission pollutant or fuel value ") + pollutant + std::string(" not found!"));
220 return 0;
221 }
222
223 if (_normedCepCurveFCvalues.find(pollutant) != _normedCepCurveFCvalues.end()) {
224 return _idlingValueFCvalues[pollutant] * ratedPower;
225 }
226 else if (_cepNormalizedCurvePollutants.find(pollutant) != _cepNormalizedCurvePollutants.end()) {
227 return _idlingValuesPollutants[pollutant] * emissionMultiplier;
228 }
229 }
230
231
233 VehicleClass->setErrMsg(std::string("Emission pollutant or fuel value ") + pollutant + std::string(" not found!"));
234 return 0;
235 }
236
237 double normalizingPower = ratedPower;
238 if (_normedCepCurveFCvalues.find(pollutant) != _normedCepCurveFCvalues.end()) {
239 emissionCurve = &_normedCepCurveFCvalues[pollutant];
240 powerPattern = &_normalizedPowerPatternFCvalues;
241 emissionMultiplier = ratedPower;
242 }
243 else if (_cepNormalizedCurvePollutants.find(pollutant) != _cepNormalizedCurvePollutants.end()) {
244 emissionCurve = &_cepNormalizedCurvePollutants[pollutant];
245 powerPattern = &_normalizedPowerPatternPollutants;
246 if (!getHeavyVehicle()) {
247 normalizingPower = drivingPower;
248 }
249 }
250
251 if (emissionCurve == nullptr || emissionCurve->empty()) {
252 VehicleClass->setErrMsg(std::string("Empty emission curve for ") + pollutant + std::string(" found!"));
253 return 0;
254 }
255 if (emissionCurve->size() == 1) {
256 return emissionCurve->front() * emissionMultiplier;
257 }
258
259 // in case that the demanded power is smaller than the first entry (smallest) in the power pattern the first is returned (should never happen)
260 if (power <= powerPattern->front() * normalizingPower) {
261 return emissionCurve->front() * emissionMultiplier;
262 }
263
264 // if power bigger than all entries in power pattern return the last (should never happen)
265 if (power >= powerPattern->back() * normalizingPower) {
266 return emissionCurve->back() * emissionMultiplier;
267 }
268
269 FindLowerUpperInPattern(lowerIndex, upperIndex, *powerPattern, power, normalizingPower);
270 return Interpolate(power, (*powerPattern)[lowerIndex] * normalizingPower, (*powerPattern)[upperIndex] * normalizingPower, (*emissionCurve)[lowerIndex], (*emissionCurve)[upperIndex]) * emissionMultiplier;
271 }
272
273 double CEP::GetCO2Emission(double _FC, double _CO, double _HC, Helpers* VehicleClass) {
274 //Declaration
275 double fCBr, fCHC, fCCO, fCCO2;
276
277 fCBr = 0;
278 fCHC = 0;
279 fCCO = 0;
280 fCCO2 = 0;
281
282 if (getFuelType() != "Mix") {
283 if (!GetfcVals(getFuelType(), fCBr, fCHC, fCCO, fCCO2, VehicleClass)) {
284 return 0;
285 }
286 }
287 else {
288 if (!CalcfCValMix(fCBr, fCHC, fCCO, fCCO2, VehicleClass)) {
289 return 0;
290 }
291 }
292
293 return (_FC * fCBr - _CO * fCCO - _HC * fCHC) / fCCO2;
294 }
295
296 bool CEP::CalcfCValMix(double& _fCBr, double& _fCHC, double& _fCCO, double& _fCCO2, Helpers* VehicleClass) {
297 //Declaration
298 double Sum = 0;
299 double sumfCBr, sumfCHC, sumfCCO, sumfCCO2;
300
301 //Initialise
302 sumfCBr = 0;
303 sumfCHC = 0;
304 sumfCCO = 0;
305 sumfCCO2 = 0;
306
307 //calculate the sum
308 for (std::map<std::string, double>::const_iterator id = _FleetMix.begin(); id != _FleetMix.end(); ++id) {
309 Sum += _FleetMix[id->first];
310 }
311
312 //Calculate the weighted fuel factors
313 if (Sum <= 0) {
314 VehicleClass->setErrMsg("All propolsion types in the fleetshares file are not known!");
315 return false;
316 }
317 else {
318 for (std::map<std::string, double>::const_iterator id = _FleetMix.begin(); id != _FleetMix.end(); ++id) {
319 if (!GetfcVals(id->first, _fCBr, _fCHC, _fCCO, _fCCO2, VehicleClass)) {
320 return false;
321 }
322 else {
323 sumfCBr += _fCBr * _FleetMix[id->first] / Sum;
324 sumfCHC += _fCHC * _FleetMix[id->first] / Sum;
325 sumfCCO += _fCCO * _FleetMix[id->first] / Sum;
326 sumfCCO2 += _fCCO2 * _FleetMix[id->first] / Sum;
327 }
328 }
329 }
330 //Result values
331 _fCBr = sumfCBr;
332 _fCHC = sumfCHC;
333 _fCCO = sumfCCO;
334 _fCCO2 = sumfCCO2;
335 return true;
336 }
337
338 bool CEP::GetfcVals(const std::string& _fuelTypex, double& _fCBr, double& _fCHC, double& _fCCO, double& _fCCO2, Helpers* VehicleClass) {
339 _fCHC = 0.866;
340 _fCCO = 0.429;
341 _fCCO2 = 0.273;
342
343//C# TO C++ CONVERTER NOTE: The following 'switch' operated on a string variable and was converted to C++ 'if-else' logic:
344// switch (_fuelTypex)
345//ORIGINAL LINE: case Constants.strGasoline:
346 if (_fuelTypex == Constants::strGasoline) {
347 _fCBr = 0.865;
348 }
349//ORIGINAL LINE: case Constants.strDiesel:
350 else if (_fuelTypex == Constants::strDiesel) {
351 _fCBr = 0.863;
352 }
353//ORIGINAL LINE: case Constants.strCNG:
354 else if (_fuelTypex == Constants::strCNG) {
355 _fCBr = 0.693;
356 _fCHC = 0.803;
357 }
358//ORIGINAL LINE: case Constants.strLPG:
359 else if (_fuelTypex == Constants::strLPG) {
360 _fCBr = 0.825;
361 _fCHC = 0.825;
362 }
363 else {
364 VehicleClass->setErrMsg(std::string("The propulsion type is not known! (") + getFuelType() + std::string(")"));
365 return false;
366 }
367 return true;
368 }
369
370 double CEP::getFMot(const double speed, const double ratedPower, const double wheelRadius) {
371 if (speed < 10e-2) {
372 return 0.;
373 }
374 //Declaration
375 int upperIndex;
376 int lowerIndex;
377
378 FindLowerUpperInPattern(lowerIndex, upperIndex, _speedPatternRotational, speed);
379 double iGear = Interpolate(speed, _speedPatternRotational[lowerIndex], _speedPatternRotational[upperIndex], _gearTransmissionCurve[lowerIndex], _gearTransmissionCurve[upperIndex]);
380
381 double iTot = iGear * _axleRatio;
382
383 double n = (30 * speed * iTot) / (wheelRadius * M_PI);
385
386 FindLowerUpperInPattern(lowerIndex, upperIndex, _nNormTable, nNorm);
387 return (-Interpolate(nNorm, _nNormTable[lowerIndex], _nNormTable[upperIndex], _dragNormTable[lowerIndex], _dragNormTable[upperIndex]) * ratedPower * 1000 / speed) / Constants::getDRIVE_TRAIN_EFFICIENCY();
388 }
389
390 double CEP::GetRotationalCoeffecient(double speed) {
391 //Declaration
392 int upperIndex;
393 int lowerIndex;
394
395 FindLowerUpperInPattern(lowerIndex, upperIndex, _speedPatternRotational, speed);
396 return Interpolate(speed, _speedPatternRotational[lowerIndex], _speedPatternRotational[upperIndex], _speedCurveRotational[lowerIndex], _speedCurveRotational[upperIndex]);
397 }
398
399 void CEP::FindLowerUpperInPattern(int& lowerIndex, int& upperIndex, const std::vector<double>& pattern, double value, double scale) {
400 lowerIndex = 0;
401 upperIndex = 0;
402
403 if (value <= pattern.front() * scale) {
404 lowerIndex = 0;
405 upperIndex = 0;
406 return;
407 }
408
409 if (value >= pattern.back() * scale) {
410 lowerIndex = (int)pattern.size() - 1;
411 upperIndex = (int)pattern.size() - 1;
412 return;
413 }
414
415 // bisection search to find correct position in power pattern
416 int middleIndex = ((int)pattern.size() - 1) / 2;
417 upperIndex = (int)pattern.size() - 1;
418 lowerIndex = 0;
419
420 while (upperIndex - lowerIndex > 1) {
421 if (pattern[middleIndex] * scale == value) {
422 lowerIndex = middleIndex;
423 upperIndex = middleIndex;
424 return;
425 }
426 else if (pattern[middleIndex] * scale < value) {
427 lowerIndex = middleIndex;
428 middleIndex = (upperIndex - lowerIndex) / 2 + lowerIndex;
429 }
430 else {
431 upperIndex = middleIndex;
432 middleIndex = (upperIndex - lowerIndex) / 2 + lowerIndex;
433 }
434 }
435 }
436
437 double CEP::Interpolate(double px, double p1, double p2, double e1, double e2) {
438 if (p2 == p1) {
439 return e1;
440 }
441
442 return e1 + (px - p1) / (p2 - p1) * (e2 - e1);
443 }
444
445 double CEP::GetPMaxNorm(double speed) {
446 // Linear function between v0 and v1, constant elsewhere
447 if (speed <= _pNormV0) {
448 return _pNormP0;
449 }
450 else if (speed >= _pNormV1) {
451 return _pNormP1;
452 }
453 else {
455 }
456 }
457
459 _massVehicle = 0;
460 _vehicleLoading = 0;
461 _vehicleMassRot = 0;
463 _cWValue = 0;
464 _resistanceF0 = 0;
465 _resistanceF1 = 0;
466 _resistanceF2 = 0;
467 _resistanceF3 = 0;
468 _resistanceF4 = 0;
469 _axleRatio = 0;
470 _auxPower = 0;
471 _pNormV0 = 0;
472 _pNormP0 = 0;
473 _pNormV1 = 0;
474 _pNormP1 = 0;
478 }
479}
bool GetfcVals(const std::string &_fuelTypex, double &_fCBr, double &_fCHC, double &_fCCO, double &_fCCO2, Helpers *VehicleClass)
void FindLowerUpperInPattern(int &lowerIndex, int &upperIndex, const std::vector< double > &pattern, double value, double scale=1.)
std::map< std::string, std::vector< double > > _normedCepCurveFCvalues
Definition V5/cpp/CEP.h:122
double GetRotationalCoeffecient(double speed)
const double & getRatedPower() const
std::vector< double > _normalizedPowerPatternFCvalues
Definition V5/cpp/CEP.h:119
std::vector< double > _dragNormTable
Definition V5/cpp/CEP.h:131
std::vector< double > _speedCurveRotational
Definition V5/cpp/CEP.h:124
void setCalcType(const std::string &value)
void InitializeInstanceFields()
double getFMot(const double speed, const double ratedPower, const double wheelRadius)
double Interpolate(double px, double p1, double p2, double e1, double e2)
const bool & getHeavyVehicle() const
void setRatedPower(const double &value)
const std::string & getCalcType() const
std::map< std::string, double > _idlingValuesPollutants
Definition V5/cpp/CEP.h:128
double GetPMaxNorm(double speed)
std::vector< double > _speedPatternRotational
Definition V5/cpp/CEP.h:118
std::vector< double > _gearTransmissionCurve
Definition V5/cpp/CEP.h:123
const std::string & getFuelType() const
double GetEmission(const std::string &pollutant, double power, double speed, Helpers *VehicleClass, const double drivingPower, const double ratedPower)
double GetCO2Emission(double _FC, double _CO, double _HC, Helpers *VehicleClass)
std::vector< double > _nNormTable
Definition V5/cpp/CEP.h:130
void setFuelType(const std::string &value)
std::map< std::string, std::vector< double > > _cepNormalizedCurvePollutants
Definition V5/cpp/CEP.h:125
double _effectiveWheelDiameter
Definition V5/cpp/CEP.h:116
double CalcEngPower(double power, const double ratedPower)
CEP(VEHPHEMLightJSON::VEH *Vehicle, std::vector< std::string > &headerLineFCvalues, std::vector< std::vector< double > > &matrixFCvalues, std::vector< std::string > &headerLinePollutants, std::vector< std::vector< double > > &matrixPollutants, std::vector< double > &idlingFCvalues, std::vector< double > &idlingPollutants)
bool CalcfCValMix(double &_fCBr, double &_fCHC, double &_fCCO, double &_fCCO2, Helpers *VehicleClass)
std::vector< double > _normalizedPowerPatternPollutants
Definition V5/cpp/CEP.h:120
std::string privateCalcType
Definition V5/cpp/CEP.h:51
std::map< std::string, double > _idlingValueFCvalues
Definition V5/cpp/CEP.h:127
std::map< std::string, double > _FleetMix
Definition V5/cpp/CEP.h:126
std::string privateFuelType
Definition V5/cpp/CEP.h:50
static const std::string HeavyVehicle
static const double & getDRIVE_TRAIN_EFFICIENCY()
static const std::string strLPG
static const std::string strCNG
static const double ZERO_SPEED_ACCURACY
static const std::string strGasoline
static const std::string strDiesel
void setErrMsg(const std::string &value)
C++ TraCI client API implementation.
#define M_PI
Definition odrSpiral.cpp:45