Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
Correction.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 <fstream>
27#include "Correction.h"
28#include "Helpers.h"
29#include "Constants.h"
30
31
32namespace PHEMlightdllV5 {
33
34 Correction::Correction(const std::vector<std::string>& dataPath)
35 : privateDataPath(dataPath) {
36 setUseDet(false);
37 setUseTNOx(false);
38 setAmbTemp(20);
39 setYear(2022);
40 setVehMileage(-1);
41 setDETFilePath("Deterioration.det");
42 setVMAFilePath("Mileage.vma");
43 setTNOxFilePath("NOxCor.tno");
44 }
45
46 const bool& Correction::getUseDet() const {
47 return privateUseDet;
48 }
49
50 void Correction::setUseDet(const bool& value) {
51 privateUseDet = value;
52 }
53
54 const std::string& Correction::getDETFilePath() const {
55 return privateDETFilePath;
56 }
57
58 void Correction::setDETFilePath(const std::string& value) {
59 privateDETFilePath = value;
60 }
61
62 const std::string& Correction::getVMAFilePath() const {
63 return privateVMAFilePath;
64 }
65
66 void Correction::setVMAFilePath(const std::string& value) {
67 privateVMAFilePath = value;
68 }
69
70 const int& Correction::getYear() const {
71 return privateYear;
72 }
73
74 void Correction::setYear(const int& value) {
75 privateYear = value;
76 }
77
78 const double& Correction::getVehMileage() const {
79 return privateVehMileage;
80 }
81
82 void Correction::setVehMileage(const double& value) {
83 privateVehMileage = value;
84 }
85
86 bool Correction::ReadDet(std::string& ErrMSG) {
87 //Read Detoriation file
88 if (!ReadDETFile(ErrMSG)) {
89 return false;
90 }
91
92 if (!ReadVMAFile(ErrMSG)) {
93 return false;
94 }
95
96 // Return value
97 return true;
98 }
99
100 bool Correction::ReadDETFile(std::string& ErrMSG) {
101 //Open file
102 std::ifstream detReader;
103 for (const std::string& p : privateDataPath) {
104 detReader.open((p + getDETFilePath()).c_str());
105 if (detReader.good()) {
106 break;
107 }
108 }
109 if (!detReader.good()) {
110 ErrMSG = "File does not exist! (" + getDETFilePath() + ")";
111 return false;
112 }
113
114 //**** DET Datei einlesen ****
115 try {
116 detReader >> DETdata;
117 } catch (...) {
118 ErrMSG = "Error during file read! (" + getDETFilePath() + ")";
119 return false;
120 }
121
122 // Return value
123 return true;
124 }
125
126 bool Correction::ReadVMAFile(std::string& ErrMSG) {
127 //Open file
128 std::ifstream vmaReader;
129 for (const std::string& p : privateDataPath) {
130 vmaReader.open((p + getVMAFilePath()).c_str());
131 if (vmaReader.good()) {
132 break;
133 }
134 }
135 if (!vmaReader.good()) {
136 ErrMSG = "File does not exist! (" + getVMAFilePath() + ")";
137 return false;
138 }
139
140 //**** VMA Datei einlesen ****
141 try {
142 vmaReader >> VMAdata;
143 } catch (...) {
144 ErrMSG = "Error during file read! (" + getVMAFilePath() + ")";
145 return false;
146 }
147
148 // Return value
149 return true;
150 }
151
153 //Initialise
154 DETFactors = std::map<std::string, double>();
155
156 if (DETdata.at("Vehicle").contains(Helper->getvClass())) {
157 if (DETdata.at("Vehicle").at(Helper->getvClass()).at("PropulsionClass").contains(Helper->getpClass())) {
158 for (const auto& it : DETdata.at("Vehicle").at(Helper->getvClass()).at("PropulsionClass").at(Helper->getpClass()).at("Emission").items()) {
159 std::string EUclass = StringUtils::replace(Helper->geteClass(), "EU", "EURO ");
160
161 //PC special classes check (ab, c, d, d-Temp). If available use otherwise use "EURO 6" if available
162 if ((Helper->getvClass() == Constants::strPKW || Helper->getvClass() == Constants::strLNF) && EUclass.length() > 6) {
163 std::string EUclassShort = EUclass.substr(0, 6);
164
165 if (!it.value().at("EUClass").contains(EUclass) && it.value().at("EUClass").contains(EUclassShort)) {
166 EUclass = EUclassShort;
167 }
168 }
169
170 //Store in upper case because retrieval will be upper case as well
171 std::string key = it.key();
172 std::transform(key.begin(), key.end(), key.begin(), [](char c) { return (char)::toupper(c); });
173 //Get the factor
174 if (it.value().at("EUClass").contains(EUclass)) {
175 const std::vector<double>& Mileage = it.value().at("Mileage");
176 const std::vector<double>& Factor = it.value().at("EUClass").at(EUclass);
177 if (getVehMileage() < 0) {
178 setVehMileage(GetMileage(Helper));
179 }
180
181 for (int i = 1; i < (int)Mileage.size(); i++) {
182 if (i == 1 && Mileage[i] > getVehMileage()) {
183 DETFactors.insert(std::make_pair(key, Factor[0]));
184 break;
185 }
186 else if (i == (int)Mileage.size() - 1 && getVehMileage() > Mileage[i]) {
187 DETFactors.insert(std::make_pair(key, Factor[i]));
188 break;
189 }
190 else if (getVehMileage() < Mileage[i]) {
191 DETFactors.insert(std::make_pair(key, Interpolate(getVehMileage(), Mileage[i - 1], Mileage[i], Factor[i - 1], Factor[i])));
192 break;
193 }
194 }
195 }
196 else {
197 DETFactors.insert(std::make_pair(key, 1));
198 }
199 }
200 }
201 }
202
203 //Return value
204 return true;
205 }
206
208 // Initialise
209 double Mileage = 0;
210
211 if (VMAdata.at("Vehicle").contains(Helper->getvClass())) {
212 if (VMAdata.at("Vehicle").at(Helper->getvClass()).at("PropulsionClass").contains(Helper->getpClass())) {
213 std::string Sclass = "0";
214//C# TO C++ CONVERTER NOTE: The following 'switch' operated on a string variable and was converted to C++ 'if-else' logic:
215// switch (Helper.sClass)
216//ORIGINAL LINE: case "":
217 if (Helper->getsClass() == "") {
218 Sclass = "0";
219 }
220//ORIGINAL LINE: case "I":
221 else if (Helper->getsClass() == "I") {
222 Sclass = "1";
223 }
224//ORIGINAL LINE: case "II":
225 else if (Helper->getsClass() == "II") {
226 Sclass = "2";
227 }
228//ORIGINAL LINE: case "III":
229 else if (Helper->getsClass() == "III") {
230 Sclass = "3";
231 }
232
233 if (VMAdata.at("Vehicle").at(Helper->getvClass()).at("PropulsionClass").at(Helper->getpClass()).at("SizeClass").contains(Sclass)) {
234 const nlohmann::json& sclassJson = VMAdata.at("Vehicle").at(Helper->getvClass()).at("PropulsionClass").at(Helper->getpClass()).at("SizeClass").at(Sclass);
235 std::string EUclass = StringUtils::replace(Helper->geteClass(), "EU", "EURO ");
236
237 //PC special classes check (ab, c, d, d-Temp). If available use otherwise use "EURO 6" if available
238 if ((Helper->getvClass() == Constants::strPKW || Helper->getvClass() == Constants::strLNF) && EUclass.length() > 6) {
239 std::string EUclassShort = EUclass.substr(0, 6);
240
241 if (!sclassJson.at("EUClass").contains(EUclass) && sclassJson.at("EUClass").contains(EUclassShort)) {
242 EUclass = EUclassShort;
243 }
244 }
245
246 if (sclassJson.contains(EUclass)) {
247 //Calculate Mileage
248 const std::vector<double>& Factor = sclassJson.at(EUclass);
249 int AnzYear = getYear() - 2020 + 1;
250 Mileage = Factor[0] * std::pow(AnzYear, 3) + Factor[1] * std::pow(AnzYear, 2) + Factor[2] * AnzYear + Factor[3];
251
252 //Check calculated mileage
253 if (Mileage < 0) {
254 Mileage = 0;
255 }
256 }
257 }
258 }
259 }
260
261
262 //Return value
263 return Mileage;
264 }
265
266 const bool& Correction::getUseTNOx() const {
267 return privateUseTNOx;
268 }
269
270 void Correction::setUseTNOx(const bool& value) {
271 privateUseTNOx = value;
272 }
273
274 const std::string& Correction::getTNOxFilePath() const {
275 return privateTNOxFilePath;
276 }
277
278 void Correction::setTNOxFilePath(const std::string& value) {
279 privateTNOxFilePath = value;
280 }
281
282 const double& Correction::getAmbTemp() const {
283 return privateAmbTemp;
284 }
285
286 void Correction::setAmbTemp(const double& value) {
287 privateAmbTemp = value;
288 }
289
290 const double& Correction::getTNOxFactor() const {
291 return privateTNOxFactor;
292 }
293
294 void Correction::setTNOxFactor(const double& value) {
295 privateTNOxFactor = value;
296 }
297
298 bool Correction::ReadTNOx(std::string& ErrMSG) {
299 //Open file
300 std::ifstream tnoxReader;
301 for (const std::string& p : privateDataPath) {
302 tnoxReader.open((p + getTNOxFilePath()).c_str());
303 if (tnoxReader.good()) {
304 break;
305 }
306 }
307 if (!tnoxReader.good()) {
308 ErrMSG = "File does not exist! (" + getTNOxFilePath() + ")";
309 return false;
310 }
311
312 //**** VMA Datei einlesen ****
313 try {
314 tnoxReader >> TNOxdata;
315 } catch (...) {
316 ErrMSG = "Error during file read! (" + getTNOxFilePath() + ")";
317 return false;
318 }
319
320 // Return value
321 return true;
322 }
323
325 //Initialise
326 setTNOxFactor(1);
327
328 //Calculation only for diesel vehicles
329 if (Helper->getpClass() != Constants::strDiesel) {
330 return true;
331 }
332
333 if (TNOxdata.at("Vehicle").contains(Helper->getvClass())) {
334 std::string EUclass = StringUtils::replace(Helper->geteClass(), "EU", "EURO ");
335
336 //PC special classes check (ab, c, d, d-Temp). If available use otherwise use "EURO 6" if available
337 if ((Helper->getvClass() == Constants::strPKW || Helper->getvClass() == Constants::strLNF) && EUclass.length() > 6) {
338 std::string EUclassShort = EUclass.substr(0, 6);
339
340 if (!TNOxdata.at("Vehicle").at(Helper->getvClass()).at("EUClass").contains(EUclass) && TNOxdata.at("Vehicle").at(Helper->getvClass()).at("EUClass").contains(EUclassShort)) {
341 EUclass = EUclassShort;
342 }
343 }
344
345
346 if (TNOxdata.at("Vehicle").at(Helper->getvClass()).at("EUClass").contains(EUclass)) {
347 //Check/set temperature borders, because calculation is a straight function
348 const nlohmann::json& EUclassJson = TNOxdata.at("Vehicle").at(Helper->getvClass()).at("EUClass").at(EUclass);
349 const double m = EUclassJson.at("m");
350 const double c = EUclassJson.at("c");
351 const double tb0 = EUclassJson.at("TB")[0];
352 if (getAmbTemp() < tb0) {
353 setTNOxFactor(m + c * tb0);
354 }
355 else if (getAmbTemp() > EUclassJson.at("TB")[1]) {
356 setTNOxFactor(1);
357 }
358 else {
359 setTNOxFactor(m + c * getAmbTemp());
360 }
361 }
362 }
363
364 //Return value
365 return true;
366 }
367
368 double Correction::Interpolate(double px, double p1, double p2, double e1, double e2) {
369 if (p2 == p1) {
370 return e1;
371 }
372
373 return e1 + (px - p1) / (p2 - p1) * (e2 - e1);
374 }
375
376}
static const std::string strLNF
static const std::string strPKW
static const std::string strDiesel
void setAmbTemp(const double &value)
const std::vector< std::string > privateDataPath
Definition Correction.h:38
bool IniDETfactor(Helpers *Helper)
const bool & getUseTNOx() const
void setTNOxFilePath(const std::string &value)
const int & getYear() const
bool IniTNOxfactor(Helpers *Helper)
std::map< std::string, double > DETFactors
Definition Correction.h:52
std::string privateDETFilePath
Definition Correction.h:39
void setDETFilePath(const std::string &value)
bool ReadVMAFile(std::string &ErrMSG)
bool ReadDet(std::string &ErrMSG)
const std::string & getTNOxFilePath() const
double Interpolate(double px, double p1, double p2, double e1, double e2)
const double & getVehMileage() const
void setTNOxFactor(const double &value)
const std::string & getDETFilePath() const
void setVMAFilePath(const std::string &value)
bool ReadTNOx(std::string &ErrMSG)
const double & getTNOxFactor() const
Correction(const std::vector< std::string > &dataPath)
std::string privateVMAFilePath
Definition Correction.h:40
std::string privateTNOxFilePath
Definition Correction.h:44
const double & getAmbTemp() const
double GetMileage(Helpers *Helper)
bool ReadDETFile(std::string &ErrMSG)
void setYear(const int &value)
void setUseTNOx(const bool &value)
void setVehMileage(const double &value)
const bool & getUseDet() const
void setUseDet(const bool &value)
const std::string & getVMAFilePath() const
const std::string & getpClass() const
const std::string & getvClass() const
const std::string & getsClass() const
const std::string & geteClass() const
static std::string replace(std::string str, const std::string &what, const std::string &by)
Replaces all occurrences of the second string by the third string within the first string.
a class to store JSON values
Definition json.hpp:17282
bool contains(KeyT &&key) const
check the existence of an element in a JSON object
Definition json.hpp:19640
iteration_proxy< iterator > items() noexcept
helper to access iterator member functions in range-based for
Definition json.hpp:19779
reference at(size_type idx)
access specified array element with bounds checking
Definition json.hpp:19090