Eclipse SUMO - Simulation of Urban MObility
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 
32 namespace 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 
207  double Correction::GetMileage(Helpers* Helper) {
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)
Definition: Correction.cpp:286
const std::vector< std::string > privateDataPath
Definition: Correction.h:38
bool IniDETfactor(Helpers *Helper)
Definition: Correction.cpp:152
const bool & getUseTNOx() const
Definition: Correction.cpp:266
void setTNOxFilePath(const std::string &value)
Definition: Correction.cpp:278
const int & getYear() const
Definition: Correction.cpp:70
bool IniTNOxfactor(Helpers *Helper)
Definition: Correction.cpp:324
nlohmann::json TNOxdata
Definition: Correction.h:107
std::map< std::string, double > DETFactors
Definition: Correction.h:52
std::string privateDETFilePath
Definition: Correction.h:39
void setDETFilePath(const std::string &value)
Definition: Correction.cpp:58
bool ReadVMAFile(std::string &ErrMSG)
Definition: Correction.cpp:126
bool ReadDet(std::string &ErrMSG)
Definition: Correction.cpp:86
const std::string & getTNOxFilePath() const
Definition: Correction.cpp:274
double Interpolate(double px, double p1, double p2, double e1, double e2)
Definition: Correction.cpp:368
nlohmann::json VMAdata
Definition: Correction.h:106
const double & getVehMileage() const
Definition: Correction.cpp:78
void setTNOxFactor(const double &value)
Definition: Correction.cpp:294
const std::string & getDETFilePath() const
Definition: Correction.cpp:54
void setVMAFilePath(const std::string &value)
Definition: Correction.cpp:66
bool ReadTNOx(std::string &ErrMSG)
Definition: Correction.cpp:298
const double & getTNOxFactor() const
Definition: Correction.cpp:290
Correction(const std::vector< std::string > &dataPath)
Definition: Correction.cpp:34
std::string privateVMAFilePath
Definition: Correction.h:40
nlohmann::json DETdata
Definition: Correction.h:105
std::string privateTNOxFilePath
Definition: Correction.h:44
const double & getAmbTemp() const
Definition: Correction.cpp:282
double GetMileage(Helpers *Helper)
Definition: Correction.cpp:207
bool ReadDETFile(std::string &ErrMSG)
Definition: Correction.cpp:100
void setYear(const int &value)
Definition: Correction.cpp:74
void setUseTNOx(const bool &value)
Definition: Correction.cpp:270
void setVehMileage(const double &value)
Definition: Correction.cpp:82
const bool & getUseDet() const
Definition: Correction.cpp:46
void setUseDet(const bool &value)
Definition: Correction.cpp:50
const std::string & getVMAFilePath() const
Definition: Correction.cpp:62
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
reference at(size_type idx)
access specified array element with bounds checking
Definition: json.hpp:19090
iteration_proxy< iterator > items() noexcept
helper to access iterator member functions in range-based for
Definition: json.hpp:19779