Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
V5/cpp/CEPHandler.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>
26#include <sstream>
27#define JSON_USE_IMPLICIT_CONVERSIONS 0
30#include "CEPHandler.h"
31#include "CEP.h"
32#include "Correction.h"
33#include "Helpers.h"
34
35
36namespace PHEMlightdllV5 {
37
40
41 const std::map<std::string, CEP*>& CEPHandler::getCEPS() const {
42 return _ceps;
43 }
44
45 bool CEPHandler::GetCEP(std::vector<std::string>& DataPath, Helpers* Helper, Correction* DataCor) {
46 if (getCEPS().find(Helper->getgClass()) == getCEPS().end()) {
47 if (!Load(DataPath, Helper, DataCor)) {
48 return false;
49 }
50 }
51 return true;
52 }
53
55 if (DataCor->getUseDet()) {
56 DataCor->setVehMileage(-1);
57 if (vehicle_Data->getMileage() > 0.) {
58 DataCor->setVehMileage(vehicle_Data->getMileage());
59 }
60
61 if (!DataCor->IniDETfactor(Helper)) {
62 return false;
63 }
64 }
65 if (DataCor->getUseTNOx()) {
66 if (!DataCor->IniTNOxfactor(Helper)) {
67 return false;
68 }
69 }
70
71 //Return value
72 return true;
73 }
74
75 bool CEPHandler::Load(std::vector<std::string>& DataPath, Helpers* Helper, Correction* DataCor, bool fleetMix) {
76 //Deklaration
77 // get string identifier for PHEM emission class
78 std::string emissionRep = Helper->getgClass();
79
80 // to hold everything.
81 std::vector<std::vector<double> > matrixFCvalues;
82 std::vector<std::vector<double> > matrixPollutants;
83 std::vector<double> idlingValuesFCvalues;
84 std::vector<double> idlingValuesPollutants;
85 std::vector<std::string> headerFCvalues;
86 std::vector<std::string> headerPollutants;
88
89 if (!ReadVehicleFile(DataPath, emissionRep, Helper, fleetMix, Vehicle)) {
90 delete Vehicle;
91 return false;
92 }
93
94 if (DataCor != nullptr) {
95 if (!CalcCorrection(DataCor, Helper, Vehicle->getVehicleData())) {
96 delete Vehicle;
97 return false;
98 }
99 }
100
101 if (!ReadEmissionData(true, DataPath, emissionRep, Helper, fleetMix, DataCor, headerFCvalues, matrixFCvalues, idlingValuesFCvalues)) {
102 delete Vehicle;
103 return false;
104 }
105 if (!ReadEmissionData(false, DataPath, emissionRep, Helper, fleetMix, DataCor, headerPollutants, matrixPollutants, idlingValuesPollutants)) {
106 delete Vehicle;
107 return false;
108 }
109
110 _ceps.insert(std::make_pair(Helper->getgClass(), new CEP(Vehicle, headerFCvalues, matrixFCvalues, headerPollutants, matrixPollutants, idlingValuesFCvalues, idlingValuesPollutants)));
111 delete Vehicle;
112 return true;
113 }
114
115 double json2double(const nlohmann::json& vd, const std::string& key) {
116 if (vd.contains(key)) {
117 return vd.at(key).get<double>();
118 }
119 return 0.;
120 }
121
122 bool CEPHandler::ReadVehicleFile(const std::vector<std::string>& DataPath, const std::string& emissionClass, Helpers* Helper, bool /* fleetMix */, VEHPHEMLightJSON::VEH*& Vehicle) {
123 std::string path = "";
125
126 //Open file
127 std::ifstream vehicleReader;
128 for (std::vector<std::string>::const_iterator i = DataPath.begin(); i != DataPath.end(); i++) {
129 vehicleReader.open(((*i) + emissionClass + ".PHEMLight.veh").c_str());
130 if (vehicleReader.good()) {
131 break;
132 }
133 }
134 if (!vehicleReader.good()) {
135 Helper->setErrMsg("File does not exist! (" + emissionClass + ".PHEMLight.veh)");
136 return false;
137 }
138
139 //**** VEH Datei einlesen ****
140 nlohmann::json json;
141 try {
142 vehicleReader >> json;
143 } catch (...) {
144 Helper->setErrMsg("Error during file read! (" + emissionClass + ".PHEMLight.veh)");
145 return false;
146 }
147
148 //*** Get the vehicle data
149 nlohmann::json::iterator vehDataIt = json.find("VehicleData");
150 if (vehDataIt == json.end()) {
151 Helper->setErrMsg("No VehicleData in " + emissionClass + ".PHEMLight.veh!");
152 return false;
153 }
154 const nlohmann::json& vd = *vehDataIt;
155 Vehicle->getVehicleData()->setMassType(vd.contains("MassType") ? vd.at("MassType").get<std::string>() : "LV");
156 Vehicle->getVehicleData()->setFuelType(vd.contains("FuelType") ? vd.at("FuelType").get<std::string>() : "D");
157 Vehicle->getVehicleData()->setCalcType(vd.contains("CalcType") ? vd.at("CalcType").get<std::string>() : "Conv");
158 Vehicle->getVehicleData()->setMass(json2double(vd, "Mass"));
159 Vehicle->getVehicleData()->setLoading(json2double(vd, "Loading"));
160 Vehicle->getVehicleData()->setRedMassWheel(json2double(vd, "RedMassWheel"));
161 Vehicle->getVehicleData()->setWheelDiameter(json2double(vd, "WheelDiameter"));
162 Vehicle->getVehicleData()->setCw(json2double(vd, "Cw"));
163 Vehicle->getVehicleData()->setA(json2double(vd, "A"));
164 Vehicle->getVehicleData()->setMileage(json2double(vd, "Mileage"));
165
166 // Auxiliaries
167 nlohmann::json::iterator auxDataIt = json.find("AuxiliariesData");
168 if (auxDataIt == json.end() || !auxDataIt->contains("Pauxnorm")) {
169 Vehicle->getAuxiliariesData()->setPauxnorm(0.);
170 } else {
171 Vehicle->getAuxiliariesData()->setPauxnorm(auxDataIt->at("Pauxnorm").get<double>());
172 }
173
174 // Engine Data
175 nlohmann::json::iterator engDataIt = json.find("EngineData");
176 if (engDataIt == json.end() || !engDataIt->contains("ICEData") || !engDataIt->contains("EMData")) {
177 Helper->setErrMsg("Incomplete EngineData in " + emissionClass + ".PHEMLight.veh!");
178 return false;
179 }
180 const nlohmann::json& iced = (*engDataIt)["ICEData"];
181 const nlohmann::json& emd = (*engDataIt)["EMData"];
182 Vehicle->getEngineData()->getICEData()->setPrated(json2double(iced, "Prated"));
183 Vehicle->getEngineData()->getICEData()->setnrated(json2double(iced, "nrated"));
184 Vehicle->getEngineData()->getICEData()->setIdling(json2double(iced, "Idling"));
185 Vehicle->getEngineData()->getEMData()->setPrated(json2double(emd, "Prated"));
186 Vehicle->getEngineData()->getEMData()->setnrated(json2double(emd, "nrated"));
187
188 // Rolling resistance
189 nlohmann::json::iterator rrDataIt = json.find("RollingResData");
190 if (rrDataIt == json.end()) {
191 Helper->setErrMsg("No RollingResData in " + emissionClass + ".PHEMLight.veh!");
192 return false;
193 }
194 const nlohmann::json& rrd = *rrDataIt;
195 Vehicle->getRollingResData()->setFr0(json2double(rrd, "Fr0"));
196 Vehicle->getRollingResData()->setFr1(json2double(rrd, "Fr1"));
197 Vehicle->getRollingResData()->setFr2(json2double(rrd, "Fr2"));
198 Vehicle->getRollingResData()->setFr3(json2double(rrd, "Fr3"));
199 Vehicle->getRollingResData()->setFr4(json2double(rrd, "Fr4"));
200
201 // Transmission
202 nlohmann::json::iterator trDataIt = json.find("TransmissionData");
203 if (trDataIt == json.end()) {
204 Helper->setErrMsg("No TransmissionData in " + emissionClass + ".PHEMLight.veh!");
205 return false;
206 }
207 Vehicle->getTransmissionData()->setAxelRatio(json2double(*trDataIt, "AxelRatio"));
208 nlohmann::json::iterator transmIt = trDataIt->find("Transm");
209 if (transmIt == trDataIt->end()) {
210 Helper->setErrMsg(std::string("Transmission ratios missing in vehicle file! Calculation stopped! (") + path + std::string(")"));
211 return false;
212 } else {
213 if (!transmIt->contains("Speed")) {
214 Helper->setErrMsg(std::string("No Speed signal in transmission data given! Calculation stopped! (") + path + std::string(")"));
215 return false;
216 }
217 if (!transmIt->contains("GearRatio")) {
218 Helper->setErrMsg(std::string("No GearRatio signal in transmission data given! Calculation stopped! (") + path + std::string(")"));
219 return false;
220 }
221 if (!transmIt->contains("RotMassF")) {
222 Helper->setErrMsg(std::string("No RotMassF signal in transmission data given! Calculation stopped! (") + path + std::string(")"));
223 return false;
224 }
225 }
226 Vehicle->getTransmissionData()->setTransm(transmIt->get<std::map<std::string, std::vector<double> > >());
227
228 // Full load and drag
229 nlohmann::json::iterator fldDataIt = json.find("FLDData");
230 if (fldDataIt == json.end()) {
231 Helper->setErrMsg("No FLDData in " + emissionClass + ".PHEMLight.veh!");
232 return false;
233 }
234 const nlohmann::json& fld = *fldDataIt;
235 Vehicle->getFLDData()->setP_n_max_v0(json2double(fld, "P_n_max_v0"));
236 Vehicle->getFLDData()->setP_n_max_p0(json2double(fld, "P_n_max_p0"));
237 Vehicle->getFLDData()->setP_n_max_v1(json2double(fld, "P_n_max_v1"));
238 Vehicle->getFLDData()->setP_n_max_p1(json2double(fld, "P_n_max_p1"));
239 nlohmann::json::iterator dragIt = fldDataIt->find("DragCurve");
240 if (dragIt == fldDataIt->end()) {
241 Helper->setErrMsg(std::string("Drag curve missing in vehicle file! Calculation stopped! (") + path + std::string(")"));
242 return false;
243 } else {
244 if (!dragIt->contains("n_norm")) {
245 Helper->setErrMsg(std::string("No n_norm signal in drag curve data given! Calculation stopped! (") + path + std::string(")"));
246 return false;
247 }
248 if (!dragIt->contains("pe_drag_norm")) {
249 Helper->setErrMsg(std::string("No pe_drag_norm signal in drag curve data given! Calculation stopped! (") + path + std::string(")"));
250 return false;
251 }
252 }
253 Vehicle->getFLDData()->setDragCurve(dragIt->get<std::map<std::string, std::vector<double> > >());
254
255 return true;
256 }
257
258 bool CEPHandler::ReadEmissionData(bool readFC, const std::vector<std::string>& DataPath, const std::string& emissionClass, Helpers* Helper, bool /* fleetMix */, Correction* DataCor, std::vector<std::string>& header, std::vector<std::vector<double> >& matrix, std::vector<double>& idlingValues) {
259 // declare file stream
260 std::string line;
261 std::string path = "";
262 header = std::vector<std::string>();
263 matrix = std::vector<std::vector<double> >();
264 idlingValues = std::vector<double>();
265
266 std::string pollutantExtension = "";
267 if (readFC) {
268 pollutantExtension += std::string("_FC");
269 }
270
271 std::ifstream fileReader;
272 for (std::vector<std::string>::const_iterator i = DataPath.begin(); i != DataPath.end(); i++) {
273 fileReader.open(((*i) + emissionClass + pollutantExtension + ".csv").c_str());
274 if (fileReader.good()) {
275 break;
276 }
277 }
278 if (!fileReader.good()) {
279 Helper->setErrMsg("File does not exist! (" + emissionClass + pollutantExtension + ".csv)");
280 return false;
281 }
282
283 // read header line for pollutant identifiers
284 if ((line = ReadLine(fileReader)) != "") {
285 const std::vector<std::string>& entries = split(line, ',');
286 // skip first entry "Pe"
287 for (int i = 1; i < (int)entries.size(); i++) {
288 header.push_back(entries[i]);
289 }
290 }
291
292 // skip units
293 ReadLine(fileReader);
294
295 // skip comment
296 ReadLine(fileReader);
297
298 //readIdlingValues
299 line = ReadLine(fileReader);
300
301 std::vector<std::string> stringIdlings = split(line, ',');
302 stringIdlings.erase(stringIdlings.begin());
303
304 idlingValues = todoubleList(stringIdlings);
305
306 while ((line = ReadLine(fileReader)) != "") {
307 matrix.push_back(todoubleList(split(line, ',')));
308 }
309
310 //Data correction (Det & TNOx)
311 if (!CorrectEmissionData(DataCor, header, matrix, idlingValues)) {
312 Helper->setErrMsg("Error in correction calculation");
313 return false;
314 }
315
316 //Return value
317 return true;
318 }
319
320 bool CEPHandler::CorrectEmissionData(Correction* DataCor, std::vector<std::string>& header, std::vector<std::vector<double> >& matrix, std::vector<double>& idlingValues) {
321 for (int i = 0; i < (int)header.size(); i++) {
322 double CorF = GetDetTempCor(DataCor, header[i]);
323 if (CorF != 1) {
324 for (int j = 0; j < (int)matrix.size(); j++) {
325 matrix[j][i + 1] *= CorF;
326 }
327 idlingValues[i] *= CorF;
328 }
329 }
330
331 //Return value
332 return true;
333 }
334
335 double CEPHandler::GetDetTempCor(Correction* DataCor, const std::string& Emi) {
336 //Initialisation
337 double CorF = 1;
338 std::string emi = Emi;
339 std::transform(emi.begin(), emi.end(), emi.begin(), [](char c) { return (char)::toupper(c); });
340
341 if (DataCor != 0) {
342 if (DataCor->getUseDet() && DataCor->DETFactors.count(emi) > 0) {
343 CorF += DataCor->DETFactors[emi] - 1;
344 }
345 if (DataCor->getUseTNOx()) {
346 if (emi.find("NOX") != std::string::npos) {
347 CorF += (DataCor->getTNOxFactor() - 1);
348 }
349 }
350 }
351
352 //Return value
353 return CorF;
354 }
355
356 const std::vector<std::string> CEPHandler::split(const std::string& s, char delim) {
357 std::vector<std::string> elems;
358 std::stringstream ss(s);
359 std::string item;
360 while (std::getline(ss, item, delim)) {
361 elems.push_back(item);
362 }
363 return elems;
364 }
365
366 double CEPHandler::todouble(const std::string& s) {
367 std::stringstream ss(s);
368 double item;
369 ss >> item;
370 return item;
371 }
372
373 std::vector<double> CEPHandler::todoubleList(const std::vector<std::string>& s) {
374 std::vector<double> result;
375 for (std::vector<std::string>::const_iterator i = s.begin(); i != s.end(); ++i) {
376 result.push_back(todouble(*i));
377 }
378 return result;
379 }
380
381 std::string CEPHandler::ReadLine(std::ifstream& s) {
382 std::string line;
383 std::getline(s, line);
384 size_t lastNWChar = line.find_last_not_of(" \n\r\t");
385 if (lastNWChar != std::string::npos) {
386 line.erase(lastNWChar + 1);
387 }
388 return line;
389 }
390
391 const std::string& VEHPHEMLightJSON::VEH::getType() const {
392 return privateType;
393 }
394
395 void VEHPHEMLightJSON::VEH::setType(const std::string& value) {
396 privateType = value;
397 }
398
399 const std::string& VEHPHEMLightJSON::VEH::getVersion() const {
400 return privateVersion;
401 }
402
403 void VEHPHEMLightJSON::VEH::setVersion(const std::string& value) {
404 privateVersion = value;
405 }
406
410
412 return &privateAuxiliariesData;
413 }
414
418
422
426
430
432 return privateMassType;
433 }
434
435 void VEHPHEMLightJSON::Vehicle_Data::setMassType(const std::string& value) {
436 privateMassType = value;
437 }
438
440 return privateFuelType;
441 }
442
443 void VEHPHEMLightJSON::Vehicle_Data::setFuelType(const std::string& value) {
444 privateFuelType = value;
445 }
446
448 return privateCalcType;
449 }
450
451 void VEHPHEMLightJSON::Vehicle_Data::setCalcType(const std::string& value) {
452 privateCalcType = value;
453 }
454
456 return privateMass;
457 }
458
459 void VEHPHEMLightJSON::Vehicle_Data::setMass(const double& value) {
460 privateMass = value;
461 }
462
464 return privateLoading;
465 }
466
468 privateLoading = value;
469 }
470
472 return privateRedMassWheel;
473 }
474
476 privateRedMassWheel = value;
477 }
478
480 return privateWheelDiameter;
481 }
482
484 privateWheelDiameter = value;
485 }
486
488 return privateCw;
489 }
490
491 void VEHPHEMLightJSON::Vehicle_Data::setCw(const double& value) {
492 privateCw = value;
493 }
494
496 return privateA;
497 }
498
499 void VEHPHEMLightJSON::Vehicle_Data::setA(const double& value) {
500 privateA = value;
501 }
502
504 return privateMileage;
505 }
506
508 privateMileage = value;
509 }
510
512 return privateFr0;
513 }
514
515 void VEHPHEMLightJSON::Rollres_Data::setFr0(const double& value) {
516 privateFr0 = value;
517 }
518
520 return privateFr1;
521 }
522
523 void VEHPHEMLightJSON::Rollres_Data::setFr1(const double& value) {
524 privateFr1 = value;
525 }
526
528 return privateFr2;
529 }
530
531 void VEHPHEMLightJSON::Rollres_Data::setFr2(const double& value) {
532 privateFr2 = value;
533 }
534
536 return privateFr3;
537 }
538
539 void VEHPHEMLightJSON::Rollres_Data::setFr3(const double& value) {
540 privateFr3 = value;
541 }
542
544 return privateFr4;
545 }
546
547 void VEHPHEMLightJSON::Rollres_Data::setFr4(const double& value) {
548 privateFr4 = value;
549 }
550
554
558
560 return privatePrated;
561 }
562
563 void VEHPHEMLightJSON::ICE_Data::setPrated(const double& value) {
564 privatePrated = value;
565 }
566
568 return privatenrated;
569 }
570
571 void VEHPHEMLightJSON::ICE_Data::setnrated(const double& value) {
572 privatenrated = value;
573 }
574
576 return privateIdling;
577 }
578
579 void VEHPHEMLightJSON::ICE_Data::setIdling(const double& value) {
580 privateIdling = value;
581 }
582
584 return privatePrated;
585 }
586
587 void VEHPHEMLightJSON::EM_Data::setPrated(const double& value) {
588 privatePrated = value;
589 }
590
592 return privatenrated;
593 }
594
595 void VEHPHEMLightJSON::EM_Data::setnrated(const double& value) {
596 privatenrated = value;
597 }
598
600 return privatePauxnorm;
601 }
602
603 void VEHPHEMLightJSON::Aux_Data::setPauxnorm(const double& value) {
604 privatePauxnorm = value;
605 }
606
608 return privateP_n_max_v0;
609 }
610
612 privateP_n_max_v0 = value;
613 }
614
616 return privateP_n_max_p0;
617 }
618
620 privateP_n_max_p0 = value;
621 }
622
624 return privateP_n_max_v1;
625 }
626
628 privateP_n_max_v1 = value;
629 }
630
632 return privateP_n_max_p1;
633 }
634
636 privateP_n_max_p1 = value;
637 }
638
639 std::map<std::string, std::vector<double> >& VEHPHEMLightJSON::FullLoadDrag_Data::getDragCurve() {
640 return privateDragCurve;
641 }
642
643 void VEHPHEMLightJSON::FullLoadDrag_Data::setDragCurve(const std::map<std::string, std::vector<double> >& value) {
644 privateDragCurve = value;
645 }
646
648 setDragCurve(std::map<std::string, std::vector<double> >());
649 }
650
652 return privateAxelRatio;
653 }
654
656 privateAxelRatio = value;
657 }
658
659 std::map<std::string, std::vector<double> >& VEHPHEMLightJSON::Transmission_Data::getTransm() {
660 return privateTransm;
661 }
662
663 void VEHPHEMLightJSON::Transmission_Data::setTransm(const std::map<std::string, std::vector<double> >& value) {
664 privateTransm = value;
665 }
666
668 setTransm(std::map<std::string, std::vector<double> >());
669 }
670}
bool Load(std::vector< std::string > &DataPath, Helpers *Helper, Correction *DataCor, bool fleetMix=false)
const std::map< std::string, CEP * > & getCEPS() const
bool ReadVehicleFile(const std::vector< std::string > &DataPath, const std::string &emissionClass, Helpers *Helper, bool fleetMix, VEHPHEMLightJSON::VEH *&Vehicle)
std::string ReadLine(std::ifstream &s)
std::vector< double > todoubleList(const std::vector< std::string > &s)
double todouble(const std::string &s)
bool CorrectEmissionData(Correction *DataCor, std::vector< std::string > &header, std::vector< std::vector< double > > &matrix, std::vector< double > &idlingValues)
bool CalcCorrection(Correction *DataCor, Helpers *Helper, VEHPHEMLightJSON::Vehicle_Data *vehicle_Data)
std::map< std::string, CEP * > _ceps
bool GetCEP(std::vector< std::string > &DataPath, Helpers *Helper, Correction *DataCor)
const std::vector< std::string > split(const std::string &s, char delim)
double GetDetTempCor(Correction *DataCor, const std::string &Emi)
bool ReadEmissionData(bool readFC, const std::vector< std::string > &DataPath, const std::string &emissionClass, Helpers *Helper, bool fleetMix, Correction *DataCor, std::vector< std::string > &header, std::vector< std::vector< double > > &matrix, std::vector< double > &idlingValues)
bool IniDETfactor(Helpers *Helper)
const bool & getUseTNOx() const
bool IniTNOxfactor(Helpers *Helper)
std::map< std::string, double > DETFactors
Definition Correction.h:52
const double & getTNOxFactor() const
void setVehMileage(const double &value)
const bool & getUseDet() const
const std::string & getgClass() const
void setErrMsg(const std::string &value)
std::map< std::string, std::vector< double > > & getDragCurve()
void setDragCurve(const std::map< std::string, std::vector< double > > &value)
void setTransm(const std::map< std::string, std::vector< double > > &value)
std::map< std::string, std::vector< double > > & getTransm()
void setType(const std::string &value)
void setVersion(const std::string &value)
C++ TraCI client API implementation.
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
auto get() const noexcept(noexcept(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))) -> decltype(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))
get a (pointer) value (explicit)
Definition json.hpp:18898
a template for a bidirectional iterator for the basic_json class This class implements a both iterato...
Definition json.hpp:11407
double json2double(const nlohmann::json &vd, const std::string &key)