From 1008c183f0e5f3312dad7e6f8d2d60d7c5b1ceb5 Mon Sep 17 00:00:00 2001 From: Sebastian Buck <38660441+frunika@users.noreply.github.com> Date: Sun, 14 Feb 2021 23:26:50 +0100 Subject: [PATCH] first working example --- example/README.md | 14 + example/Vissim_PHEMlight.cfg | 8 + example/phem_light_example.inpx | 2110 ++++++++++++++++++ example/phem_light_example.layx | 1185 ++++++++++ example/phem_light_example1.sig | 79 + example/phem_vehicles/PC_D_EU4.PHEMLight.veh | 134 ++ example/phem_vehicles/PC_D_EU4.csv | 35 + example/phem_vehicles/PC_D_EU4_FC.csv | 17 + example/phem_vehicles/PC_G_EU4.PHEMLight.veh | 133 ++ example/phem_vehicles/PC_G_EU4.csv | 35 + example/phem_vehicles/PC_G_EU4_FC.csv | 17 + example/phem_vehicles/README.md | 3 + src/EmissionModel.cpp | 496 ++++ src/EmissionModel.h | 221 ++ src/PHEMlight/CEP.cpp | 467 ++++ src/PHEMlight/CEP.h | 174 ++ src/PHEMlight/CEPHandler.cpp | 383 ++++ src/PHEMlight/CEPHandler.h | 95 + src/PHEMlight/CMakeLists.txt | 13 + src/PHEMlight/Constants.cpp | 67 + src/PHEMlight/Constants.h | 86 + src/PHEMlight/Helpers.cpp | 272 +++ src/PHEMlight/Helpers.h | 99 + src/PHEMlight/README.md | 3 + src/PHEMlight/conversion.patch | 573 +++++ src/PHEMlightHandler.cpp | 682 ++++++ src/PHEMlightHandler.h | 140 ++ src/Vissim_PHEMlight.vcxproj | 275 +++ 28 files changed, 7816 insertions(+) create mode 100644 example/README.md create mode 100644 example/Vissim_PHEMlight.cfg create mode 100644 example/phem_light_example.inpx create mode 100644 example/phem_light_example.layx create mode 100644 example/phem_light_example1.sig create mode 100644 example/phem_vehicles/PC_D_EU4.PHEMLight.veh create mode 100644 example/phem_vehicles/PC_D_EU4.csv create mode 100644 example/phem_vehicles/PC_D_EU4_FC.csv create mode 100644 example/phem_vehicles/PC_G_EU4.PHEMLight.veh create mode 100644 example/phem_vehicles/PC_G_EU4.csv create mode 100644 example/phem_vehicles/PC_G_EU4_FC.csv create mode 100644 example/phem_vehicles/README.md create mode 100644 src/EmissionModel.cpp create mode 100644 src/EmissionModel.h create mode 100644 src/PHEMlight/CEP.cpp create mode 100644 src/PHEMlight/CEP.h create mode 100644 src/PHEMlight/CEPHandler.cpp create mode 100644 src/PHEMlight/CEPHandler.h create mode 100644 src/PHEMlight/CMakeLists.txt create mode 100644 src/PHEMlight/Constants.cpp create mode 100644 src/PHEMlight/Constants.h create mode 100644 src/PHEMlight/Helpers.cpp create mode 100644 src/PHEMlight/Helpers.h create mode 100644 src/PHEMlight/README.md create mode 100644 src/PHEMlight/conversion.patch create mode 100644 src/PHEMlightHandler.cpp create mode 100644 src/PHEMlightHandler.h create mode 100644 src/Vissim_PHEMlight.vcxproj diff --git a/example/README.md b/example/README.md new file mode 100644 index 0000000..049ec50 --- /dev/null +++ b/example/README.md @@ -0,0 +1,14 @@ +# Vissim PHEMlight example + +There are three links in this Vissim model. + +All three links have the same traffic volume and the same driving behavior. +On each link, the passenger cars are influenced by a traffic signal. + +For each vehicle, different emissions are calculated using PHEMlight during the simulation. +On the left link, the vehicle input contains passenger cars with emission class Euro 4, powered by **gasoline**. +On the right side passenger cars with **diesel** Euro 4. +On the middle link, both vehicle types have equal shares. + +The colors of the link segments show the calculated NOx emissions. +The bars show the fuel consumption. diff --git a/example/Vissim_PHEMlight.cfg b/example/Vissim_PHEMlight.cfg new file mode 100644 index 0000000..43e8c9f --- /dev/null +++ b/example/Vissim_PHEMlight.cfg @@ -0,0 +1,8 @@ +# Path to PHEMlight vehicles files (.csv, .PHEMLight.veh, _FC.csv) +# "PATH = [RelPath]" +PATH = .\phem_vehicles\ + +# VISSIM_ID ; PHEM_VEHICLE_TYPE ; PHEM_POWER_TYPE ; PHEM_EU_CLASS +DEFAULT;PC;G;EU4 +100;PC;G;EU4 +101;PC;D;EU4 diff --git a/example/phem_light_example.inpx b/example/phem_light_example.inpx new file mode 100644 index 0000000..619afb7 --- /dev/null +++ b/example/phem_light_example.inpx @@ -0,0 +1,2110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/example/phem_light_example.layx b/example/phem_light_example.layx new file mode 100644 index 0000000..797b70e --- /dev/null +++ b/example/phem_light_example.layx @@ -0,0 +1,1185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/example/phem_light_example1.sig b/example/phem_light_example1.sig new file mode 100644 index 0000000..ce04002 --- /dev/null +++ b/example/phem_light_example1.sig @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/example/phem_vehicles/PC_D_EU4.PHEMLight.veh b/example/phem_vehicles/PC_D_EU4.PHEMLight.veh new file mode 100644 index 0000000..c283a9f --- /dev/null +++ b/example/phem_vehicles/PC_D_EU4.PHEMLight.veh @@ -0,0 +1,134 @@ +c PHEMLight Vehicle Input filefc (based on PHEM .veh file format) +c PHEM 11.7.5 CO2 map test 2 +c 02.02.2016 08:16:17 +c Vehicle mass [kg] +1500 +c Vehicle loading [kg] +50 +c Cd value [-] +0.3113 +c Cross sectional area [m^2] +2.16 +c Delta [-] (not supported since Version 10.7) +0 +c Engine rotational inertia [kg*m^2] +0.5234 +c Wheels equivalent rotational inertia [kg] (= I_wheel/rdyn^2) +41.3424 +c Gearbox rotational inertia [kg*m^2] +0.06046 +c Auxiliaries base power demand (normalized) [-] +0 +c Engine rated power [kW] +93 +c Engine rated speed [rpm] +4073 +c Engine idling speed [rpm] +816 +c --- +0 +c Rolling resistance coefficients +c Fr0 +0.009 +c Fr1 +5E-05 +c Fr2 +0 +c Fr3 +0 +c Fr4 +1.6E-09 +c --- +0 +c Transmission loss factor +0.3 +c Transmission +c Axle ratio [-] +3.7284, +c Wheel effective diameter [m] +0.6264 +c Transmission gears: Ratio [-], path to efficiency map filefc (optional) +c Gear 1 +3.7079, +c Gear 2 +2.0237, +c Gear 3 +1.2784, +c Gear 4 +0.9359, +c Gear 5 +0.7414, +c Gear 6 +0.6162, +c Gear 7 +0, +c Gear 8 +0, +c Gear 9 +0, +c Gear 10 +0, +c Gear 11 +0, +c Gear 12 +0, +c Gear 13 +0, +c Gear 14 +0, +c Gear 15 +0, +c Gear 16 +0, +c Gear shift behaviour: +c Gearshift model (Version fast driver) +c shift up at ratio rpm/rated rpm in actual gear greater than +0.7840928 +c shift down when rpm/rated rpm in lower gear is higher than +0.6081684 +c Gearshift model (Version economic driver) +c shift up at ratio rpm/rated rpm in higher gear greater than +0.5601891 +c Shift down when ratio rpm/rated rpm in actual gear is lower than +0.5202062 +c Share of version economic driver (0 to 1) +0 +c Share of version mixed model (0 to 1) +1 +cVehiclemasstypeforPHEMlight +LV +cFueltypeforPHEMlight +D +c P_n_max_v0 +5 +c P_n_max_p0 +0.13 +c P_n_max_v1 +26 +c P_n_max_p1 +0.75 +c vehicle speed [km/h] (converted to m/s after read-in), gear ratio [-], rotational mass factor [-] +0,3.7079,1.67 +10.53695,3.7079,1.67 +28.99677,2.0237,1.2 +43.68127,1.2784,1.08 +69.56696,0.9359,1.05 +94.3671,0.7414,1.03 +121.0647,0.6162,1.02 +250,0.6162,1.02 +c n_norm, pe_drag _norm +0,-0.015 +0.002,-0.015 +0.05,-0.017 +0.1,-0.02 +0.2,-0.028 +0.3,-0.039 +0.4,-0.05 +0.5,-0.063 +0.6,-0.078 +0.7,-0.098 +0.8,-0.121 +0.9,-0.145 +1,-0.169 +1.1,-0.198 +1.2,-0.232 diff --git a/example/phem_vehicles/PC_D_EU4.csv b/example/phem_vehicles/PC_D_EU4.csv new file mode 100644 index 0000000..250a23e --- /dev/null +++ b/example/phem_vehicles/PC_D_EU4.csv @@ -0,0 +1,35 @@ +cp_norm(drive),NOx,HC,CO,PM,PN,NO +[-],[g/h],[g/h],[g/h],[g/h],[#/h],[g/h] +Pdrive (Engine)= 22.11115,Extrapolation: Pe: -1.5 - -1.25; 3.75 - 6 +idle,5.95534,0.1406479,0.2413937,0.1616896,1.11E+14,3.26342 +-1.5,0,0,0,0,0,0 +-1.25,0,0,0,0,0,0 +-1,1.8106,0.1140485,0.3899072,0.1578594,1.86E+14,1.028107 +-0.75,3.51163,0.2084584,0.8743084,0.3038903,3.63E+14,1.98543 +-0.5,6.389799,0.3229104,1.062626,0.438556,5.73E+14,3.632768 +-0.25,9.399384,0.4154986,0.844896,0.5310611,7.27E+14,5.378731 +0,12.03175,0.4185574,0.7594641,0.5656357,7.72E+14,6.873875 +0.25,19.22764,0.5726808,1.368716,0.8483028,1.17E+15,11.00196 +0.5,30.78983,0.6917911,1.977875,1.225236,1.63E+15,17.84461 +0.75,44.01824,0.7626554,2.612527,1.687364,2.14E+15,25.59621 +1,66.45253,0.8137084,2.968721,2.221274,2.83E+15,39.10237 +1.25,81.7254,0.8343465,3.192058,2.407159,3.09E+15,47.86955 +1.5,111.2948,0.9483307,3.222644,2.798034,3.77E+15,66.01514 +1.75,130.983,0.9917992,3.103828,2.876693,4.16E+15,77.40793 +2,155.5134,0.9762785,3.366468,2.696024,4.13E+15,90.57925 +2.25,210.9117,0.9075134,4.5983105,2.965473,4.37E+15,119.3683 +2.5,220.5246,1.006408,5.830153,3.234922,4.62E+15,125.0741 +2.75,258.9931,1.087851,5.325302,3.504371,4.86E+15,148.5889 +3,279.6105,1.318822,5.325302,3.77382,5.10E+15,164.0854 +3.25,281.7131,1.479041,5.325302,5.258993,6.24E+15,166.602 +3.5,300.451,1.598447,5.325302,6.99257,7.02E+15,179.9282 +3.75,321.9117,1.712622,5.325302,7.49204,7.52E+15,192.7802 +4,343.3725,1.826797,5.325302,7.991509,8.02E+15,205.6322 +4.25,364.8333,1.940972,5.325302,8.490978,8.52E+15,218.4842 +4.5,386.2941,2.055147,5.325302,8.990448,9.02E+15,231.3362 +4.75,407.7549,2.169322,5.325302,9.489918,9.53E+15,244.1882 +5,429.2157,2.283496,5.325302,9.989388,1.00E+16,257.0402 +5.25,450.6765,2.397671,5.325302,10.48886,1.05E+16,269.8922 +5.5,472.1372,2.511846,5.325302,10.98833,1.10E+16,282.7443 +5.75,493.598,2.626021,5.325302,11.4878,1.15E+16,295.5963 +6,515.0588,2.740196,5.325302,11.98727,1.20E+16,308.4483 \ No newline at end of file diff --git a/example/phem_vehicles/PC_D_EU4_FC.csv b/example/phem_vehicles/PC_D_EU4_FC.csv new file mode 100644 index 0000000..65ba0f8 --- /dev/null +++ b/example/phem_vehicles/PC_D_EU4_FC.csv @@ -0,0 +1,17 @@ +cp_norm(rated),FC +[-],[g/kWrated] +Pdrive (Engine)= 22.11115,Extrapolation: Pe: 0.9000001 - 1 +idle,6.225238 +-0.2,3.632487 +-0.1,11.32746 +0,18.48723 +0.1,33.5591 +0.2,52.99504 +0.3,72.9073 +0.4,93.49616 +0.5,106.7572 +0.6,120.398 +0.7,145.4391 +0.8000001,157.9092 +0.9000001,177.6479 +1,197.3865 diff --git a/example/phem_vehicles/PC_G_EU4.PHEMLight.veh b/example/phem_vehicles/PC_G_EU4.PHEMLight.veh new file mode 100644 index 0000000..99403ac --- /dev/null +++ b/example/phem_vehicles/PC_G_EU4.PHEMLight.veh @@ -0,0 +1,133 @@ +c PHEMLight Vehicle Input filefc (based on PHEM .veh file format) +c PHEM 11.7.5 CO2 map test 2 +c 02.02.2016 08:16:31 +c Vehicle mass [kg] +1235 +c Vehicle loading [kg] +50 +c Cd value [-] +0.3113 +c Cross sectional area [m^2] +2.11756 +c Delta [-] (not supported since Version 10.7) +0 +c Engine rotational inertia [kg*m^2] +0.5 +c Wheels equivalent rotational inertia [kg] (= I_wheel/rdyn^2) +40 +c Gearbox rotational inertia [kg*m^2] +0.06 +c Auxiliaries base power demand (normalized) [-] +0 +c Engine rated power [kW] +72 +c Engine rated speed [rpm] +5565 +c Engine idling speed [rpm] +798 +c --- +0 +c Rolling resistance coefficients +c Fr0 +0.009 +c Fr1 +5E-05 +c Fr2 +0 +c Fr3 +0 +c Fr4 +1.6E-09 +c --- +0 +c Transmission loss factor +0.3 +c Transmission +c Axle ratio [-] +4.0826, +c Wheel effective diameter [m] +0.6064 +c Transmission gears: Ratio [-], path to efficiency map filefc (optional) +c Gear 1 +3.6298, +c Gear 2 +2.0523, +c Gear 3 +1.3801, +c Gear 4 +1.0477, +c Gear 5 +0.8423, +c Gear 6 +0, +c Gear 7 +0, +c Gear 8 +0, +c Gear 9 +0, +c Gear 10 +0, +c Gear 11 +0, +c Gear 12 +0, +c Gear 13 +0, +c Gear 14 +0, +c Gear 15 +0, +c Gear 16 +0, +c Gear shift behaviour: +c Gearshift model (Version fast driver) +c shift up at ratio rpm/rated rpm in actual gear greater than +0.768717 +c shift down when rpm/rated rpm in lower gear is higher than +0.5802642 +c Gearshift model (Version economic driver) +c shift up at ratio rpm/rated rpm in higher gear greater than +0.5288679 +c Shift down when ratio rpm/rated rpm in actual gear is lower than +0.4860377 +c Share of version economic driver (0 to 1) +0 +c Share of version mixed model (0 to 1) +1 +cVehiclemasstypeforPHEMlight +LV +cFueltypeforPHEMlight +G +c P_n_max_v0 +5 +c P_n_max_p0 +0.15 +c P_n_max_v1 +40 +c P_n_max_p1 +0.8 +c vehicle speed [km/h] (converted to m/s after read-in), gear ratio [-], rotational mass factor [-] +0,3.6298,2.008095 +12.31168,3.6298,2.008095 +29.96561,2.0523,1.316293 +44.09933,1.3801,1.145397 +69.54142,1.0477,1.077003 +103.4718,0.8423,1.053688 +250,0.8423,1.053688 +c n_norm, pe_drag _norm +0,-0.012 +0.071,-0.017 +0.128,-0.022 +0.186,-0.026 +0.244,-0.03 +0.302,-0.034 +0.419,-0.043 +0.535,-0.052 +0.651,-0.06 +0.768,-0.069 +0.884,-0.078 +1,-0.086 +1.117,-0.095 +1.233,-0.103 +1.349,-0.112 diff --git a/example/phem_vehicles/PC_G_EU4.csv b/example/phem_vehicles/PC_G_EU4.csv new file mode 100644 index 0000000..04cba8c --- /dev/null +++ b/example/phem_vehicles/PC_G_EU4.csv @@ -0,0 +1,35 @@ +cp_norm(drive),NOx,HC,CO,PM,PN,NO +[-],[g/h],[g/h],[g/h],[g/h],[#/h],[g/h] +Pdrive (Engine)= 19.39067,Extrapolation: Pe: -1.5 - -1.25; 3.25 - 6 +idle,0.2311568,0.06580322,1.57672,0.0005531011,3.260417E+12,0.2195987 +-1.5,0,0,0,0,0,0 +-1.25,0,0,0,0,0,0 +-1,0.1968537,0.06040405,5.746554,0.03304507,2.077539E+13,0.187011 +-0.75,0.1930701,0.07494506,2.899907,0.007002674,1.137434E+13,0.1834166 +-0.5,0.5213834,0.1307903,5.15753,0.01752782,1.968342E+13,0.4953142 +-0.25,0.8236781,0.1857997,8.30414,0.02386856,1.933813E+13,0.7824941 +0,1.078666,0.1541283,8.331351,0.02075658,1.713567E+13,1.024733 +0.25,1.767643,0.1910141,9.857034,0.01829969,2.435022E+13,1.679261 +0.5,2.494093,0.2603717,12.36965,0.03831597,3.629912E+13,2.369388 +0.75,3.85773,0.4649452,25.95141,0.1305431,6.79121E+13,3.664844 +1,6.102762,0.7786441,46.99697,0.2287794,1.022273E+14,5.797623 +1.25,10.26341,1.321729,101.1859,0.3713556,1.602917E+14,9.750237 +1.5,13.74077,1.955556,169.1437,0.5279462,2.559291E+14,13.05373 +1.75,14.35727,2.592299,221.4526,0.8213891,3.838289E+14,13.63941 +2,16.96906,3.493875,328.9751,1.21975,6.99455E+14,16.1206 +2.25,19.37725,3.967094,467.4081,2.652949,1.071518E+15,18.40839 +2.5,22.78092,7.104819,1068.183,3.925668,1.288203E+15,21.64187 +2.75,25.44913,8.668326,1614.103,3.719576,1.454951E+15,24.17667 +3,24.04244,13.18394,2765.932,3.426118,1.709202E+15,22.84032 +3.25,26.04598,14.2826,2996.426,3.711627,1.851635E+15,24.74368 +3.5,28.04951,15.38126,3226.921,3.997137,1.994069E+15,26.64704 +3.75,30.05305,16.47993,3457.415,4.282647,2.136502E+15,28.5504 +4,32.05659,17.57859,3687.909,4.568157,2.278936E+15,30.45376 +4.25,34.06012,18.67725,3918.404,4.853666,2.421369E+15,32.35712 +4.5,36.06366,19.77591,4148.898,5.139176,2.563803E+15,34.26048 +4.75,38.0672,20.87457,4379.392,5.424685,2.706236E+15,36.16384 +5,40.07073,21.97323,4609.886,5.710195,2.84867E+15,38.0672 +5.25,42.07427,23.07189,4840.38,5.995705,2.991103E+15,39.97055 +5.5,44.0778,24.17056,5070.875,6.281214,3.133536E+15,41.87391 +5.75,46.08134,25.26922,5301.369,6.566724,3.27597E+15,43.77727 +6,48.08488,26.36788,5531.863,6.852233,3.418403E+15,45.68063 diff --git a/example/phem_vehicles/PC_G_EU4_FC.csv b/example/phem_vehicles/PC_G_EU4_FC.csv new file mode 100644 index 0000000..1fc6f3b --- /dev/null +++ b/example/phem_vehicles/PC_G_EU4_FC.csv @@ -0,0 +1,17 @@ +cp_norm(rated),FC +[-],[g/kWrated] +Pdrive (Engine)= 19.39067,Extrapolation: Pe: 0.9000001 - 1 +idle,10.82388 +-0.2,4.366878 +-0.1,15.2459 +0,24.06894 +0.1,40.95275 +0.2,63.58941 +0.3,87.5217 +0.4,109.7244 +0.5,136.4364 +0.6,160.0468 +0.7,190.6633 +0.8000001,210.6401 +0.9000001,236.9701 +1,263.3002 diff --git a/example/phem_vehicles/README.md b/example/phem_vehicles/README.md new file mode 100644 index 0000000..bdfe8b7 --- /dev/null +++ b/example/phem_vehicles/README.md @@ -0,0 +1,3 @@ +# Origin + +Forked from [sumo](https://github.com/eclipse/sumo/tree/master/data/emissions/PHEMlight) diff --git a/src/EmissionModel.cpp b/src/EmissionModel.cpp new file mode 100644 index 0000000..bab5c35 --- /dev/null +++ b/src/EmissionModel.cpp @@ -0,0 +1,496 @@ +/********************************************************************************/ +// Vissim PHEMlight Handler +// Copyright (C) 2021 Karlsruhe Institut of Technology (KIT), https://ifv.kit.edu +// PHEMlight module +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0/ +// SPDX-License-Identifier: EPL-2.0 +/********************************************************************************/ +/// @file EmissionModel.cpp +/// @author Sebastian Buck +/// @author Oliver Neumann +/// @date 2021/02/14 +/// +/// Based on an example provided by Lukas Kautzsch +// +/****************************************************************************/ + +#include "EmissionModel.h" +#include "PHEMlightHandler.h" + +#define DEBUG_EMISSION_MODEL 0 + +#if DEBUG_EMISSION_MODEL > 0 + +#include +#include + +std::ofstream debug_emission_model("emissionmodel.txt"); + +#endif + +#define PROFILE_EMISSION_MODEL 0 + +#if PROFILE_EMISSION_MODEL > 0 + +#include +#include + +#include +using default_time = std::chrono::nanoseconds; + +std::ofstream profile_em("profile_em.txt"); + +#endif + +phem_light_handler phem = phem_light_handler(); + +/*==========================================================================*/ + +BOOL APIENTRY DllMain(HANDLE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + +/*==========================================================================*/ + +EMISSIONMODEL_API int EmissionModelSetValue(long type, + long index1, + long index2, + long long_value, + double double_value, + char *string_value) +{ + /* Sets the value of a data object of type , selected by */ + /* and possibly , to , or */ + /* <*string_value> (object and value selection depending on ). */ + /* Return value is 1 on success, otherwise 0. */ + +#if DEBUG_EMISSION_MODEL >= 3 + debug_emission_model << " \t\t type: " << type + << " index1: " << index1 + << " index2: " << index2 + << " long_value: " << long_value + << " double_value: " << double_value; + + switch (type) + { + case EMISSION_DATA_TIMESTEP: + debug_emission_model << ";\t\t // EMISSION_DATA_TIMESTEP = " << double_value << std::endl; + break; + case EMISSION_DATA_TIME: + debug_emission_model << ";\t\t // EMISSION_DATA_TIME unused parameter" << std::endl; + break; + case EMISSION_DATA_TIME_OF_DAY: + debug_emission_model << ";\t\t // EMISSION_DATA_TIME_OF_DAY unused parameter" << std::endl; + break; + case EMISSION_DATA_EMI_LEVEL: + debug_emission_model << ";\t\t // EMISSION_DATA_EMI_LEVEL unused parameter" << std::endl; + break; + case EMISSION_DATA_VEH_ID: + debug_emission_model << ";\t\t // EMISSION_DATA_VEH_ID = " << long_value << std::endl; + break; + case EMISSION_DATA_VEH_TYPE: + debug_emission_model << ";\t\t // EMISSION_DATA_VEH_TYPE = " << long_value << std::endl; + break; + case EMISSION_DATA_VEH_VELOCITY: + debug_emission_model << ";\t\t // EMISSION_DATA_VEH_VELOCITY = " << double_value << std::endl; + break; + case EMISSION_DATA_VEH_ACCELERATION: + debug_emission_model << ";\t\t // EMISSION_DATA_VEH_ACCELERATION = " << double_value << std::endl; + break; + case EMISSION_DATA_VEH_WEIGHT: + debug_emission_model << ";\t\t // EMISSION_DATA_VEH_WEIGHT = " << double_value << std::endl; + break; + case EMISSION_DATA_SLOPE: + debug_emission_model << ";\t\t // EMISSION_DATA_SLOPE = " << double_value << std::endl; + break; + case EMISSION_DATA_LINKTYPE: + debug_emission_model << ";\t\t // EMISSION_DATA_LINKTYPE unused parameter" << std::endl; + break; + default: + debug_emission_model << std::endl + << " \t\t UNKOWN SET TYPE." << std::endl; + break; + } +#endif + +#if PROFILE_EMISSION_MODEL > 0 + auto start = std::chrono::high_resolution_clock::now(); +#endif + + vehicle *veh; + switch (type) + { + case EMISSION_DATA_TIMESTEP: + buffer_timestep = double_value; + veh = phem.get_vehicle(buffer_veh_id); + if (veh != NULL) + { + veh->timestep = buffer_timestep; + } + break; + case EMISSION_DATA_TIME: + // unused parameter + break; + case EMISSION_DATA_TIME_OF_DAY: + // unused parameter + break; + case EMISSION_DATA_EMI_LEVEL: + // unused parameter + break; + case EMISSION_DATA_VEH_ID: + buffer_veh_id = long_value; + break; + case EMISSION_DATA_VEH_TYPE: + buffer_veh_type = long_value; + break; + case EMISSION_DATA_VEH_VELOCITY: + buffer_veh_velocity = double_value; + veh = phem.get_vehicle(buffer_veh_id); + if (veh != NULL) + { + veh->velocity = buffer_veh_velocity; + } + break; + case EMISSION_DATA_VEH_ACCELERATION: + buffer_veh_acceleration = double_value; + veh = phem.get_vehicle(buffer_veh_id); + if (veh != NULL) + { + veh->acceleration = buffer_veh_acceleration; + } + break; + case EMISSION_DATA_VEH_WEIGHT: + buffer_veh_weight = double_value; + veh = phem.get_vehicle(buffer_veh_id); + if (veh != NULL) + { + veh->weight = buffer_veh_weight; + } + break; + case EMISSION_DATA_SLOPE: + buffer_slope = double_value; + veh = phem.get_vehicle(buffer_veh_id); + if (veh != NULL) + { + veh->slope = buffer_slope; + } + break; + case EMISSION_DATA_LINKTYPE: + // unused parameter + break; + default: + return 0; + } +#if PROFILE_EMISSION_MODEL > 0 + auto end = std::chrono::high_resolution_clock::now(); + profile_em << "EM_SET;" << std::chrono::duration_cast(end - start).count() << std::endl; +#endif + return 1; +} + +/*--------------------------------------------------------------------------*/ + +EMISSIONMODEL_API int EmissionModelGetValue(long type, + long index1, + long index2, + long *long_value, + double *double_value, + char **string_value) +{ + /* Gets the value of a data object of type , selected by */ + /* and possibly , and writes that value to <*double_value>, */ + /* <*float_value> or <**string_value> (object and value selection */ + /* depending on ). */ + /* Return value is 1 on success, otherwise 0. */ + +#if DEBUG_EMISSION_MODEL >= 3 + debug_emission_model << " \t\t type: " << type + << " index1: " << index1 + << " index2: " << index2; + + switch (type) + { + case EMISSION_DATA_BENZ: + debug_emission_model << ";\t\t // Getting EMISSION_DATA_BENZ" << std::endl; + break; + case EMISSION_DATA_CO: + debug_emission_model << ";\t\t // Getting EMISSION_DATA_CO" << std::endl; + break; + case EMISSION_DATA_CO2: + debug_emission_model << ";\t\t // Getting EMISSION_DATA_CO2" << std::endl; + break; + case EMISSION_DATA_HC: + debug_emission_model << ";\t\t // Getting EMISSION_DATA_HC" << std::endl; + break; + case EMISSION_DATA_FUEL: + debug_emission_model << ";\t\t // Getting EMISSION_DATA_FUEL" << std::endl; + break; + case EMISSION_DATA_NMOG: + debug_emission_model << ";\t\t // Getting EMISSION_DATA_NMOG" << std::endl; + break; + case EMISSION_DATA_NMHC: + debug_emission_model << ";\t\t // Getting EMISSION_DATA_NMHC" << std::endl; + break; + case EMISSION_DATA_NOX: + debug_emission_model << ";\t\t // Getting EMISSION_DATA_NOX" << std::endl; + break; + case EMISSION_DATA_PART: + debug_emission_model << ";\t\t // Getting EMISSION_DATA_PART" << std::endl; + break; + case EMISSION_DATA_SOOT: + debug_emission_model << ";\t\t // Getting EMISSION_DATA_SOOT" << std::endl; + break; + case EMISSION_DATA_SO2: + debug_emission_model << ";\t\t // Getting EMISSION_DATA_SO2" << std::endl; + break; + case EMISSION_DATA_EVAP: + debug_emission_model << ";\t\t // Getting EMISSION_DATA_EVAP" << std::endl; + break; + default: + debug_emission_model << std::endl + << " Asking for unkown emission type " << type << "." << std::endl; + break; + } +#endif + +#if PROFILE_EMISSION_MODEL > 0 + auto start = std::chrono::high_resolution_clock::now(); +#endif + + emission *emi = NULL; + int i = 1; + switch (type) + { + case EMISSION_DATA_CO: + *double_value = 0.0; + emi = phem.get_vehicle_emission(buffer_veh_id); + if (emi != NULL) + { + *double_value = emi->co; + } +#if DEBUG_EMISSION_MODEL >= 1 + else + { + debug_emission_model << std::endl + << " phem.get_vehicle_emission( id ) found no emission!" << type << "." << std::endl; + } +#endif + break; + case EMISSION_DATA_CO2: + *double_value = 0.0; + emi = phem.get_vehicle_emission(buffer_veh_id); + if (emi != NULL) + { + *double_value = emi->co2; + } +#if DEBUG_EMISSION_MODEL >= 1 + else + { + debug_emission_model << std::endl + << " phem.get_vehicle_emission( id ) found no emission!" << type << "." << std::endl; + } +#endif + break; + case EMISSION_DATA_HC: + *double_value = 0.0; + emi = phem.get_vehicle_emission(buffer_veh_id); + if (emi != NULL) + { + *double_value = emi->hc; + } +#if DEBUG_EMISSION_MODEL >= 1 + else + { + debug_emission_model << std::endl + << " phem.get_vehicle_emission( id ) found no emission!" << type << "." << std::endl; + } +#endif + break; + case EMISSION_DATA_FUEL: + *double_value = 0.0; + emi = phem.get_vehicle_emission(buffer_veh_id); + if (emi != NULL) + { + *double_value = emi->fuel_consumption; + } +#if DEBUG_EMISSION_MODEL >= 1 + else + { + debug_emission_model << std::endl + << " phem.get_vehicle_emission( id ) found no emission!" << type << "." << std::endl; + } +#endif + break; + case EMISSION_DATA_NOX: + *double_value = 0.0; + emi = phem.get_vehicle_emission(buffer_veh_id); + if (emi != NULL) + { + *double_value = emi->nox; + } +#if DEBUG_EMISSION_MODEL >= 1 + else + { + debug_emission_model << std::endl + << " phem.get_vehicle_emission( id ) found no emission!" << type << "." << std::endl; + } +#endif + break; + case EMISSION_DATA_PART: + *double_value = 0.0; + emi = phem.get_vehicle_emission(buffer_veh_id); + if (emi != NULL) + { + *double_value = emi->pm; + } +#if DEBUG_EMISSION_MODEL >= 1 + else + { + debug_emission_model << std::endl + << " phem.get_vehicle_emission( id ) found no emission!" << type << "." << std::endl; + } +#endif + break; + case EMISSION_DATA_PM10TOT: + *double_value = 0.0; + emi = phem.get_vehicle_emission(buffer_veh_id); + if (emi != NULL) + { + *double_value = emi->pm; + } +#if DEBUG_EMISSION_MODEL >= 1 + else + { + debug_emission_model << std::endl + << " phem.get_vehicle_emission( id ) found no emission!" << type << "." << std::endl; + } +#endif + break; + case EMISSION_DATA_PM25TOT: + *double_value = 0.0; + emi = phem.get_vehicle_emission(buffer_veh_id); + if (emi != NULL) + { + *double_value = emi->pm; + } +#if DEBUG_EMISSION_MODEL >= 1 + else + { + debug_emission_model << std::endl + << " phem.get_vehicle_emission( id ) found no emission!" << type << "." << std::endl; + } +#endif + break; + default: + *double_value = 0; + break; + } +#if PROFILE_EMISSION_MODEL > 0 + auto end = std::chrono::high_resolution_clock::now(); + profile_em << "EM_GET;" << std::chrono::duration_cast(end - start).count() << std::endl; +#endif + return 1; +} + +/*==========================================================================*/ + +EMISSIONMODEL_API int EmissionModelExecuteCommand(long number) +{ + /* Executes the command if that is available in the emission */ + /* module. Return value is 1 on success, otherwise 0. */ + +#if DEBUG_EMISSION_MODEL >= 2 + switch (number) + { + case EMISSION_COMMAND_INIT: + debug_emission_model << " \t INIT" << std::endl; + break; + case EMISSION_COMMAND_CREATE_VEHICLE: + debug_emission_model << " \t Create Vehicle with ID " << buffer_veh_id << " and Type " << buffer_veh_type << "." << std::endl; + break; + case EMISSION_COMMAND_KILL_VEHICLE: + debug_emission_model << " \t Kill Vehicle with ID " << buffer_veh_id << "." << std::endl; + break; + case EMISSION_COMMAND_CALCULATE_VEHICLE: + debug_emission_model << " \t Calculate Emission" << std::endl; + break; + default: + break; + } +#endif + +#if PROFILE_EMISSION_MODEL > 0 + auto start = std::chrono::high_resolution_clock::now(); +#endif + + bool all_right = false; + switch (number) + { + case EMISSION_COMMAND_INIT: + // seems like never called + all_right = true; + break; + case EMISSION_COMMAND_CREATE_VEHICLE: + // create vehicle with given id and type from buffer + all_right = phem.create_vehicle(buffer_veh_id, buffer_veh_type); +#if DEBUG_EMISSION_MODEL >= 2 + if (!all_right) + { + debug_emission_model << " \t\t Couldn't create vehicle with id " << buffer_veh_id << " and type " << buffer_veh_type << "." << std::endl; + } +#endif + break; + case EMISSION_COMMAND_KILL_VEHICLE: + // remove vehicle with given id + all_right = phem.destroy_vehicle(buffer_veh_id); +#if DEBUG_EMISSION_MODEL >= 2 + if (!all_right) + { + debug_emission_model << " \t\t Couldn't destroy vehicle with id " << buffer_veh_id << "." << std::endl; + } +#endif + break; + case EMISSION_COMMAND_CALCULATE_VEHICLE: + /* ### call emission calculation here */ + all_right = phem.calculate_vehicle_emission(buffer_veh_id); +#if DEBUG_EMISSION_MODEL >= 2 + if (!all_right) + { + debug_emission_model << " \t\t Couldn't calculate vehicle emission with id " << buffer_veh_id << "." << std::endl; + } +#endif + break; + default: +#if DEBUG_EMISSION_MODEL >= 1 + debug_emission_model << " \t\t COMMAND " << number << " UNKOWN." << std::endl; +#endif + break; + } + +#if PROFILE_EMISSION_MODEL > 0 + auto end = std::chrono::high_resolution_clock::now(); + profile_em << "EM_EXEC;" << std::chrono::duration_cast(end - start).count() << std::endl; +#endif + + if (all_right) + { + return 1; + } + else + { + return 0; + } +} diff --git a/src/EmissionModel.h b/src/EmissionModel.h new file mode 100644 index 0000000..6b377aa --- /dev/null +++ b/src/EmissionModel.h @@ -0,0 +1,221 @@ +/********************************************************************************/ +// Vissim PHEMlight Handler +// Copyright (C) 2021 Karlsruhe Institut of Technology (KIT), https://ifv.kit.edu +// PHEMlight module +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0/ +// SPDX-License-Identifier: EPL-2.0 +/********************************************************************************/ +/// @file EmissionModel.h +/// @author Sebastian Buck +/// @author Oliver Neumann +/// @date 2021/02/14 +/// +/// Based on an example provided by Lukas Kautzsch +// +/****************************************************************************/ + +#ifndef __EMISSIONMODEL_H +#define __EMISSIONMODEL_H + +#ifndef _CONSOLE +#include +#endif + +/*==========================================================================*/ + +/* Global defines for use in cpp file. For example buffering */ +/* parameters or handling vehicle objects in map. */ + +/* general data buffer: */ +double buffer_timestep = -1; + +/* current vehicle data buffer: */ +long buffer_veh_id = -1; +long buffer_veh_type = -1; +double buffer_veh_velocity = -1; +double buffer_veh_acceleration = -1; +double buffer_veh_weight = -1; + +/* link buffer: */ +double buffer_slope = -1; + +/*==========================================================================*/ + +/* In the creation of EmissionModel.DLL all files must be compiled */ +/* with the preprocessor definition EMISSIONMODEL_EXPORTS. */ +/* Programs that use EmissionModel.DLL must not be compiled */ +/* with that preprocessor definition. */ + +#ifdef EMISSIONMODEL_EXPORTS +#define EMISSIONMODEL_API extern "C" __declspec(dllexport) +#else +#define EMISSIONMODEL_API extern "C" __declspec(dllimport) +#endif + +/*==========================================================================*/ + +/* general data: */ +#define EMISSION_DATA_TIMESTEP 101 +/* double: simulation time step length [s] */ +#define EMISSION_DATA_TIME 102 +/* double: current simulation time [s] */ +#define EMISSION_DATA_TIME_OF_DAY 103 +/* string: current simulation time [HH:MM:SS.CC, 24-hour format] */ +#define EMISSION_DATA_EMI_LEVEL 104 +/* long: EMI level in Vissim license */ + +/* current vehicle data: */ +#define EMISSION_DATA_VEH_ID 201 +/* long: vehicle number */ +#define EMISSION_DATA_VEH_TYPE 202 +/* long: vehicle type number (user defined) */ +#define EMISSION_DATA_VEH_VELOCITY 203 +/* double: current speed [m/s] */ +#define EMISSION_DATA_VEH_ACCELERATION 204 +/* double: current acceleration [m/s�] */ +#define EMISSION_DATA_VEH_WEIGHT 205 +/* double: vehicle weight [kg] */ + +/* link data: */ +#define EMISSION_DATA_SLOPE 301 +/* double: link slope [radians] */ +#define EMISSION_DATA_LINKTYPE 302 +/* double: link behavior type number */ + +/* emission data: */ +/* must be provided by the emission model after EMISSION_COMMAND_CALCULATE */ +/* for GetValue() */ +#define EMISSION_DATA_BENZ 801 +/* double: benzene emissions [g/s] in the current time step */ +#define EMISSION_DATA_CO 802 +/* double: carbon monoxide emissions [g/s] in the current time step */ +#define EMISSION_DATA_CO2 803 +/* double: carbon dioxide emissions [g/s] in the current time step */ +#define EMISSION_DATA_HC 804 +/* double: hydrocarbon emissions [g/s] in the current time step */ +#define EMISSION_DATA_FUEL 805 +/* double: fuel consumption [g/s] in the current time step */ +#define EMISSION_DATA_NMOG 806 +/* double: nonmethane organic gas emissions [g/s] in the current time step */ +#define EMISSION_DATA_NMHC 807 +/* double: nonmethane hydrocarbon emissions [g/s] in the current time step */ +#define EMISSION_DATA_NOX 808 +/* double: nitrogen oxide emissions [g/s] in the current time step */ +#define EMISSION_DATA_PART 809 +/* double: particulate emissions [g/s] in the current time step */ +#define EMISSION_DATA_SOOT 810 +/* double: soot emissions [g/s] in the current time step */ +#define EMISSION_DATA_SO2 811 +/* double: sulfur dioxide emissions [g/s] in the current time step */ +#define EMISSION_DATA_EVAP 812 +/* double: evaporation HC emissions [g/s] in the current time step */ +#define EMISSION_DATA_224TMP 813 +/* double: 2,2,4-trimethylpentane emissions [g/s] in the current time step */ +#define EMISSION_DATA_CH4 814 +/* double: methane emissions [g/s] in the current time step */ +#define EMISSION_DATA_ELEM_C 815 +/* double: elemental carbon emissions [g/s] in the current time step */ +#define EMISSION_DATA_ETHYLBENZ 816 +/* double: ethyl benzene emissions [g/s] in the current time step */ +#define EMISSION_DATA_MTBE 817 +/* double: methyl tert-butyl ether emissions [g/s] in the current time step */ +#define EMISSION_DATA_N2O 818 +/* double: dinitrogene monoxide emissions [g/s] in the current time step */ +#define EMISSION_DATA_NH3 819 +/* double: ammonia emissions [g/s] in the current time step */ +#define EMISSION_DATA_NO3 820 +/* double: nitrate emissions [g/s] in the current time step */ +#define EMISSION_DATA_PM10BRA 821 +/* double: PM10 brakewear emissions [g/s] in the current time step */ +#define EMISSION_DATA_PM10TIR 822 +/* double: PM10 tirewear emissions [g/s] in the current time step */ +#define EMISSION_DATA_PM10TOT 823 +/* double: PM10 total emissions [g/s] in the current time step */ +#define EMISSION_DATA_PM25BRA 824 +/* double: PM2.5 brakewear emissions [g/s] in the current time step */ +#define EMISSION_DATA_PM25TIR 825 +/* double: PM2.5 tirewear emissions [g/s] in the current time step */ +#define EMISSION_DATA_PM25TOT 826 +/* double: PM2.5 total emissions [g/s] in the current time step */ +#define EMISSION_DATA_SULF_PART 827 +/* double: sulfate particulate emissions [g/s] in the current time step */ +#define EMISSION_DATA_TOG 828 +/* double: total organic gases emissions [g/s] in the current time step */ +#define EMISSION_DATA_TOLUENE 829 +/* double: toluene emissions [g/s] in the current time step */ +#define EMISSION_DATA_VOC 830 +/* double: volatile organic compounds emissions [g/s] in the current time step */ +#define EMISSION_DATA_XYLENE 831 +/* double: xylene emissions [g/s] in the current time step */ +#define EMISSION_DATA_13BUT 832 +/* double: 1,3-butadiene emissions [g/s] in the current time step */ +#define EMISSION_DATA_FORMALD 833 +/* double: formaldheyde emissions [g/s] in the current time step */ +#define EMISSION_DATA_ACETALD 834 +/* double: acetaldehyde emissions [g/s] in the current time step */ +#define EMISSION_DATA_HEXANE 835 +/* double: hexane emissions [g/s] in the current time step */ +#define EMISSION_DATA_NAPHT_GAS 836 +/* double: naphtalene gas emissions [g/s] in the current time step */ + +/*--------------------------------------------------------------------------*/ + +EMISSIONMODEL_API int EmissionModelSetValue(long type, + long index1, + long index2, + long long_value, + double double_value, + char *string_value); + +/* Sets the value of a data object of type , selected by */ +/* and possibly , to , or */ +/* <*string_value> (object and value selection depending on ). */ +/* Return value is 1 on success, otherwise 0. */ + +/*--------------------------------------------------------------------------*/ + +EMISSIONMODEL_API int EmissionModelGetValue(long type, + long index1, + long index2, + long *long_value, + double *double_value, + char **string_value); + +/* Gets the value of a data object of type , selected by */ +/* and possibly , and writes that value to <*double_value>, */ +/* <*float_value> or <**string_value> (object and value selection */ +/* depending on ). */ +/* Return value is 1 on success, otherwise 0. */ + +/*==========================================================================*/ + +#define EMISSION_COMMAND_INIT 0 +/* called from VISSIM once at the start of a simulation run */ +/* values set before: EMISSION_DATA_TIMESTEP */ +/* EMISSION_DATA_TIME */ + +#define EMISSION_COMMAND_CREATE_VEHICLE 1 +/* called from VISSIM once per vehicle entering the network */ +/* values set before: EMISSION_DATA_VEH_ID */ +/* EMISSION_DATA_VEH_TYPE */ + +#define EMISSION_COMMAND_KILL_VEHICLE 2 +/* called from VISSIM once per vehicle leaving the network */ +/* value set before: EMISSION_DATA_VEH_ID */ + +#define EMISSION_COMMAND_CALCULATE_VEHICLE 3 +/* called from VISSIM once per time step during a simulation run */ +/* values set before: all values */ + +/*--------------------------------------------------------------------------*/ + +EMISSIONMODEL_API int EmissionModelExecuteCommand(long number); + +/* Executes the command if that is available in the emission */ +/* module. Return value is 1 on success, otherwise 0. */ + +/*==========================================================================*/ + +#endif /* __EMISSIONMODEL_H */ diff --git a/src/PHEMlight/CEP.cpp b/src/PHEMlight/CEP.cpp new file mode 100644 index 0000000..51962c3 --- /dev/null +++ b/src/PHEMlight/CEP.cpp @@ -0,0 +1,467 @@ +/****************************************************************************/ +// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo +// Copyright (C) 2016-2021 German Aerospace Center (DLR) and others. +// PHEMlight module +// Copyright (C) 2016-2017 Technische Universitaet Graz, https://www.tugraz.at/ +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0/ +// This Source Code may also be made available under the following Secondary +// Licenses when the conditions for such availability set forth in the Eclipse +// Public License 2.0 are satisfied: GNU General Public License, version 2 +// or later which is available at +// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html +// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later +/****************************************************************************/ +/// @file CEP.cpp +/// @author Martin Dippold +/// @author Michael Behrisch +/// @date July 2016 +/// +// +/****************************************************************************/ + + +#include "CEP.h" +#include "Constants.h" +#include "Helpers.h" + + +namespace PHEMlightdll { + + CEP::CEP(bool heavyVehicle, double vehicleMass, double vehicleLoading, double vehicleMassRot, double crossArea, double cWValue, double f0, double f1, double f2, double f3, double f4, double axleRatio, std::vector& transmissionGearRatios, double auxPower, double ratedPower, double engineIdlingSpeed, double engineRatedSpeed, double effictiveWheelDiameter, double pNormV0, double pNormP0, double pNormV1, double pNormP1, const std::string& vehicelFuelType, std::vector >& matrixFC, std::vector& headerLinePollutants, std::vector >& matrixPollutants, std::vector >& matrixSpeedRotational, std::vector >& normedDragTable, double idlingFC, std::vector& idlingPollutants) { + (void)transmissionGearRatios; // just to make the compiler happy about the unused parameter + InitializeInstanceFields(); + _resistanceF0 = f0; + _resistanceF1 = f1; + _resistanceF2 = f2; + _resistanceF3 = f3; + _resistanceF4 = f4; + _cWValue = cWValue; + _crossSectionalArea = crossArea; + _massVehicle = vehicleMass; + _vehicleLoading = vehicleLoading; + _vehicleMassRot = vehicleMassRot; + _ratedPower = ratedPower; + _engineIdlingSpeed = engineIdlingSpeed; + _engineRatedSpeed = engineRatedSpeed; + _effectiveWheelDiameter = effictiveWheelDiameter; + _heavyVehicle = heavyVehicle; + _fuelType = vehicelFuelType; + _axleRatio = axleRatio; + _auxPower = auxPower; + + _pNormV0 = pNormV0 / 3.6; + _pNormP0 = pNormP0; + _pNormV1 = pNormV1 / 3.6; + _pNormP1 = pNormP1; + + std::vector pollutantIdentifier; + std::vector > pollutantMeasures; + std::vector > normalizedPollutantMeasures; + + // init pollutant identifiers + for (int i = 0; i < (int)headerLinePollutants.size(); i++) { + pollutantIdentifier.push_back(headerLinePollutants[i]); + } + + // initialize measures + for (int i = 0; i < (int)headerLinePollutants.size(); i++) { + pollutantMeasures.push_back(std::vector()); + normalizedPollutantMeasures.push_back(std::vector()); + } + + // looping through matrix and assigning values for speed rotational table + _speedCurveRotational = std::vector(); + _speedPatternRotational = std::vector(); + _gearTransmissionCurve = std::vector(); + for (int i = 0; i < (int)matrixSpeedRotational.size(); i++) { + if (matrixSpeedRotational[i].size() != 3) { + return; + } + + _speedPatternRotational.push_back(matrixSpeedRotational[i][0] / 3.6); + _gearTransmissionCurve.push_back(matrixSpeedRotational[i][1]); + _speedCurveRotational.push_back(matrixSpeedRotational[i][2]); + } + + // looping through matrix and assigning values for drag table + _nNormTable = std::vector(); + _dragNormTable = std::vector(); + for (int i = 0; i < (int)normedDragTable.size(); i++) { + if (normedDragTable[i].size() != 2) { + return; + } + + _nNormTable.push_back(normedDragTable[i][0]); + _dragNormTable.push_back(normedDragTable[i][1]); + } + + // looping through matrix and assigning values for Fuel consumption + _cepCurveFC = std::vector(); + _normedCepCurveFC = std::vector(); + _powerPatternFC = std::vector(); + _normalizedPowerPatternFC = std::vector(); + for (int i = 0; i < (int)matrixFC.size(); i++) { + if (matrixFC[i].size() != 2) { + return; + } + + _powerPatternFC.push_back(matrixFC[i][0] * _ratedPower); + _normalizedPowerPatternFC.push_back(matrixFC[i][0]); + _cepCurveFC.push_back(matrixFC[i][1] * _ratedPower); + _normedCepCurveFC.push_back(matrixFC[i][1]); + + } + + _powerPatternPollutants = std::vector(); + + double pollutantMultiplyer = 1; + + _drivingPower = _normalizingPower = CalcPower(Constants::NORMALIZING_SPEED, Constants::NORMALIZING_ACCELARATION, 0); + + // looping through matrix and assigning values for pollutants + if (heavyVehicle) { + _normalizingPower = _ratedPower; + _normalizingType = NormalizingType_RatedPower; + pollutantMultiplyer = _ratedPower; + } + else { + _normalizingPower = _drivingPower; + _normalizingType = NormalizingType_DrivingPower; + } + + _normailzedPowerPatternPollutants = std::vector(); + + _cepNormalizedCurvePollutants = std::map >(); + + int headerCount = (int)headerLinePollutants.size(); + for (int i = 0; i < (int)matrixPollutants.size(); i++) { + for (int j = 0; j < (int)matrixPollutants[i].size(); j++) { + if ((int)matrixPollutants[i].size() != headerCount + 1) { + return; + } + + if (j == 0) { + _normailzedPowerPatternPollutants.push_back(matrixPollutants[i][j]); + _powerPatternPollutants.push_back(matrixPollutants[i][j] * getNormalizingPower()); + } + else { + pollutantMeasures[j - 1].push_back(matrixPollutants[i][j] * pollutantMultiplyer); + normalizedPollutantMeasures[j - 1].push_back(matrixPollutants[i][j]); + } + } + } + + _cepCurvePollutants = std::map >(); + _idlingValuesPollutants = std::map(); + + for (int i = 0; i < (int)headerLinePollutants.size(); i++) { + _cepCurvePollutants.insert(std::make_pair(pollutantIdentifier[i], pollutantMeasures[i])); + _cepNormalizedCurvePollutants.insert(std::make_pair(pollutantIdentifier[i], normalizedPollutantMeasures[i])); + _idlingValuesPollutants.insert(std::make_pair(pollutantIdentifier[i], idlingPollutants[i] * pollutantMultiplyer)); + } + + _idlingValueFC = idlingFC * _ratedPower; + } + + const bool& CEP::getHeavyVehicle() const { + return _heavyVehicle; + } + + const std::string& CEP::getFuelType() const { + return _fuelType; + } + + const CEP::NormalizingType& CEP::getNormalizingTypeX() const { + return _normalizingType; + } + + const double& CEP::getRatedPower() const { + return _ratedPower; + } + + void CEP::setRatedPower(const double& value) { + _ratedPower = value; + } + + const double& CEP::getNormalizingPower() const { + return _normalizingPower; + } + + const double& CEP::getDrivingPower() const { + return _drivingPower; + } + + void CEP::setDrivingPower(const double& value) { + _drivingPower = value; + } + + double CEP::CalcPower(double speed, double acc, double gradient) { + //Declaration + double power = 0; + double rotFactor = GetRotationalCoeffecient(speed); + double powerAux = (_auxPower * _ratedPower); + + //Calculate the power + power += (_massVehicle + _vehicleLoading) * Constants::GRAVITY_CONST * (_resistanceF0 + _resistanceF1 * speed + _resistanceF4 * std::pow(speed, 4)) * speed; + power += (_crossSectionalArea * _cWValue * Constants::AIR_DENSITY_CONST / 2) * std::pow(speed, 3); + power += (_massVehicle * rotFactor + _vehicleMassRot + _vehicleLoading) * acc * speed; + power += (_massVehicle + _vehicleLoading) * Constants::GRAVITY_CONST * gradient * 0.01 * speed; + power /= 1000; + power /= Constants::_DRIVE_TRAIN_EFFICIENCY; + power += powerAux; + + //Return result + return power; + } + + double CEP::CalcEngPower(double power) { + if (power < _powerPatternFC.front()) { + return _powerPatternFC.front(); + } + if (power > _powerPatternFC.back()) { + return _powerPatternFC.back(); + } + + return power; + } + + double CEP::GetEmission(const std::string& pollutant, double power, double speed, Helpers* VehicleClass) { + //Declaration + std::vector emissionCurve; + std::vector powerPattern; + + // bisection search to find correct position in power pattern + int upperIndex; + int lowerIndex; + + if (_fuelType != Constants::strBEV) { + if (std::abs(speed) <= Constants::ZERO_SPEED_ACCURACY) { + if (pollutant == "FC") { + return _idlingValueFC; + } + else { + if (_cepCurvePollutants.find(pollutant) == _cepCurvePollutants.end()) { + VehicleClass->setErrMsg(std::string("Emission pollutant ") + pollutant + std::string(" not found!")); + return 0; + } + + return _idlingValuesPollutants[pollutant]; + } + } + } + + if (pollutant == "FC") { + emissionCurve = _cepCurveFC; + powerPattern = _powerPatternFC; + } + else { + if (_cepCurvePollutants.find(pollutant) == _cepCurvePollutants.end()) { + VehicleClass->setErrMsg(std::string("Emission pollutant ") + pollutant + std::string(" not found!")); + return 0; + } + + emissionCurve = _cepCurvePollutants[pollutant]; + powerPattern = _powerPatternPollutants; + } + + if (emissionCurve.empty()) { + VehicleClass->setErrMsg(std::string("Empty emission curve for ") + pollutant + std::string(" found!")); + return 0; + } + if (emissionCurve.size() == 1) { + return emissionCurve[0]; + } + + // in case that the demanded power is smaller than the first entry (smallest) in the power pattern the first is returned (should never happen) + if (power <= powerPattern.front()) { + return emissionCurve[0]; + } + + // if power bigger than all entries in power pattern return the last (should never happen) + if (power >= powerPattern.back()) { + return emissionCurve.back(); + } + + FindLowerUpperInPattern(lowerIndex, upperIndex, powerPattern, power); + return Interpolate(power, powerPattern[lowerIndex], powerPattern[upperIndex], emissionCurve[lowerIndex], emissionCurve[upperIndex]); + } + + double CEP::GetCO2Emission(double _FC, double _CO, double _HC, Helpers* VehicleClass) { + //Declaration + double fCBr; + double fCHC = 0.866; + double fCCO = 0.429; + double fCCO2 = 0.273; + +//C# TO C++ CONVERTER NOTE: The following 'switch' operated on a string variable and was converted to C++ 'if-else' logic: +// switch (_fuelType) +//ORIGINAL LINE: case Constants.strGasoline: + if (_fuelType == Constants::strGasoline) { + fCBr = 0.865; + } +//ORIGINAL LINE: case Constants.strDiesel: + else if (_fuelType == Constants::strDiesel) { + fCBr = 0.863; + } +//ORIGINAL LINE: case Constants.strCNG: + else if (_fuelType == Constants::strCNG) { + fCBr = 0.693; + fCHC = 0.803; + } +//ORIGINAL LINE: case Constants.strLPG: + else if (_fuelType == Constants::strLPG) { + fCBr = 0.825; + fCHC = 0.825; + } + else { + VehicleClass->setErrMsg(std::string("The propolsion type is not known! (") + _fuelType + std::string(")")); + return 0; + } + + return (_FC * fCBr - _CO * fCCO - _HC * fCHC) / fCCO2; + } + + double CEP::GetDecelCoast(double speed, double acc, double gradient) { + //Declaration + int upperIndex; + int lowerIndex; + + if (speed < Constants::SPEED_DCEL_MIN) { + return speed / Constants::SPEED_DCEL_MIN * GetDecelCoast(Constants::SPEED_DCEL_MIN, acc, gradient); + } + + double rotCoeff = GetRotationalCoeffecient(speed); + FindLowerUpperInPattern(lowerIndex, upperIndex, _speedPatternRotational, speed); + double iGear = Interpolate(speed, _speedPatternRotational[lowerIndex], _speedPatternRotational[upperIndex], _gearTransmissionCurve[lowerIndex], _gearTransmissionCurve[upperIndex]); + + double iTot = iGear * _axleRatio; + + double n = (30 * speed * iTot) / ((_effectiveWheelDiameter / 2) * M_PI); + double nNorm = (n - _engineIdlingSpeed) / (_engineRatedSpeed - _engineIdlingSpeed); + + FindLowerUpperInPattern(lowerIndex, upperIndex, _nNormTable, nNorm); + + double fMot = 0; + + if (speed >= 10e-2) { + fMot = (-Interpolate(nNorm, _nNormTable[lowerIndex], _nNormTable[upperIndex], _dragNormTable[lowerIndex], _dragNormTable[upperIndex]) * _ratedPower * 1000 / speed) / 0.9; + } + + double fRoll = (_resistanceF0 + _resistanceF1 * speed + std::pow(_resistanceF2 * speed, 2) + std::pow(_resistanceF3 * speed, 3) + std::pow(_resistanceF4 * speed, 4)) * (_massVehicle + _vehicleLoading) * Constants::GRAVITY_CONST; + + double fAir = _cWValue * _crossSectionalArea * 1.2 * 0.5 * std::pow(speed, 2); + + double fGrad = (_massVehicle + _vehicleLoading) * Constants::GRAVITY_CONST * gradient / 100; + + return -(fMot + fRoll + fAir + fGrad) / ((_massVehicle + _vehicleLoading) * rotCoeff); + } + + double CEP::GetRotationalCoeffecient(double speed) { + //Declaration + int upperIndex; + int lowerIndex; + + FindLowerUpperInPattern(lowerIndex, upperIndex, _speedPatternRotational, speed); + return Interpolate(speed, _speedPatternRotational[lowerIndex], _speedPatternRotational[upperIndex], _speedCurveRotational[lowerIndex], _speedCurveRotational[upperIndex]); + } + + void CEP::FindLowerUpperInPattern(int& lowerIndex, int& upperIndex, std::vector& pattern, double value) { + lowerIndex = 0; + upperIndex = 0; + + if (value <= pattern.front()) { + lowerIndex = 0; + upperIndex = 0; + return; + } + + if (value >= pattern.back()) { + lowerIndex = (int)pattern.size() - 1; + upperIndex = (int)pattern.size() - 1; + return; + } + + // bisection search to find correct position in power pattern + int middleIndex = ((int)pattern.size() - 1) / 2; + upperIndex = (int)pattern.size() - 1; + lowerIndex = 0; + + while (upperIndex - lowerIndex > 1) { + if (pattern[middleIndex] == value) { + lowerIndex = middleIndex; + upperIndex = middleIndex; + return; + } + else if (pattern[middleIndex] < value) { + lowerIndex = middleIndex; + middleIndex = (upperIndex - lowerIndex) / 2 + lowerIndex; + } + else { + upperIndex = middleIndex; + middleIndex = (upperIndex - lowerIndex) / 2 + lowerIndex; + } + } + + if (pattern[lowerIndex] <= value && value < pattern[upperIndex]) { + return; + } + } + + double CEP::Interpolate(double px, double p1, double p2, double e1, double e2) { + if (p2 == p1) { + return e1; + } + + return e1 + (px - p1) / (p2 - p1) * (e2 - e1); + } + + double CEP::GetMaxAccel(double speed, double gradient) { + double rotFactor = GetRotationalCoeffecient(speed); + double pMaxForAcc = GetPMaxNorm(speed) * _ratedPower - CalcPower(speed, 0, gradient); + + return (pMaxForAcc * 1000) / ((_massVehicle * rotFactor + _vehicleMassRot + _vehicleLoading) * speed); + } + + double CEP::GetPMaxNorm(double speed) { + // Linear function between v0 and v1, constant elsewhere + if (speed <= _pNormV0) { + return _pNormP0; + } + else if (speed >= _pNormV1) { + return _pNormP1; + } + else { + return Interpolate(speed, _pNormV0, _pNormV1, _pNormP0, _pNormP1); + } + } + + void CEP::InitializeInstanceFields() { + _heavyVehicle = false; + _normalizingType = static_cast(0); + _ratedPower = 0; + _normalizingPower = 0; + _drivingPower = 0; + _massVehicle = 0; + _vehicleLoading = 0; + _vehicleMassRot = 0; + _crossSectionalArea = 0; + _cWValue = 0; + _resistanceF0 = 0; + _resistanceF1 = 0; + _resistanceF2 = 0; + _resistanceF3 = 0; + _resistanceF4 = 0; + _axleRatio = 0; + _auxPower = 0; + _pNormV0 = 0; + _pNormP0 = 0; + _pNormV1 = 0; + _pNormP1 = 0; + _engineRatedSpeed = 0; + _engineIdlingSpeed = 0; + _effectiveWheelDiameter = 0; + _idlingValueFC = 0; + } +} diff --git a/src/PHEMlight/CEP.h b/src/PHEMlight/CEP.h new file mode 100644 index 0000000..0518e40 --- /dev/null +++ b/src/PHEMlight/CEP.h @@ -0,0 +1,174 @@ +/****************************************************************************/ +// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo +// Copyright (C) 2016-2021 German Aerospace Center (DLR) and others. +// PHEMlight module +// Copyright (C) 2016-2017 Technische Universitaet Graz, https://www.tugraz.at/ +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0/ +// This Source Code may also be made available under the following Secondary +// Licenses when the conditions for such availability set forth in the Eclipse +// Public License 2.0 are satisfied: GNU General Public License, version 2 +// or later which is available at +// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html +// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later +/****************************************************************************/ +/// @file CEP.h +/// @author Martin Dippold +/// @author Michael Behrisch +/// @date July 2016 +/// +// +/****************************************************************************/ + + +#ifndef PHEMlightCEP +#define PHEMlightCEP + +#define _USE_MATH_DEFINES +#include +#include +#include +#include +#include + +//C# TO C++ CONVERTER NOTE: Forward class declarations: +namespace PHEMlightdll { class Helpers; } + + +namespace PHEMlightdll { + class CEP { + //-------------------------------------------------------------------------------------------------- + // Constructors + //-------------------------------------------------------------------------------------------------- + + public: + CEP(bool heavyVehicle, double vehicleMass, double vehicleLoading, double vehicleMassRot, double crossArea, double cWValue, double f0, double f1, double f2, double f3, double f4, double axleRatio, std::vector& transmissionGearRatios, double auxPower, double ratedPower, double engineIdlingSpeed, double engineRatedSpeed, double effictiveWheelDiameter, double pNormV0, double pNormP0, double pNormV1, double pNormP1, const std::string& vehicelFuelType, std::vector >& matrixFC, std::vector& headerLinePollutants, std::vector >& matrixPollutants, std::vector >& matrixSpeedRotational, std::vector >& normedDragTable, double idlingFC, std::vector& idlingPollutants); + + + //-------------------------------------------------------------------------------------------------- + // Members + //-------------------------------------------------------------------------------------------------- + + private: + bool _heavyVehicle; + public: + const bool& getHeavyVehicle() const; + + private: + std::string _fuelType; + public: + const std::string& getFuelType() const; + + public: + enum NormalizingType { + NormalizingType_RatedPower, + NormalizingType_DrivingPower + }; + private: + NormalizingType _normalizingType; + public: + const NormalizingType& getNormalizingTypeX() const; + + private: + double _ratedPower; + public: + const double& getRatedPower() const; + void setRatedPower(const double& value); + + private: + double _normalizingPower; + public: + const double& getNormalizingPower() const; + + private: + double _drivingPower; + public: + const double& getDrivingPower() const; + void setDrivingPower(const double& value); + + + + protected: + double _massVehicle; + double _vehicleLoading; + double _vehicleMassRot; + double _crossSectionalArea; + double _cWValue; + double _resistanceF0; + double _resistanceF1; + double _resistanceF2; + double _resistanceF3; + double _resistanceF4; + double _axleRatio; + double _auxPower; + double _pNormV0; + double _pNormP0; + double _pNormV1; + double _pNormP1; + + double _engineRatedSpeed; + double _engineIdlingSpeed; + double _effectiveWheelDiameter; + + std::vector _speedPatternRotational; + std::vector _powerPatternFC; + std::vector _normalizedPowerPatternFC; + std::vector _normailzedPowerPatternPollutants; + std::vector _powerPatternPollutants; + + std::vector _cepCurveFC; + std::vector _normedCepCurveFC; + std::vector _gearTransmissionCurve; + std::vector _speedCurveRotational; + std::map > _cepCurvePollutants; + std::map > _cepNormalizedCurvePollutants; + double _idlingValueFC; + std::map _idlingValuesPollutants; + + std::vector _nNormTable; + std::vector _dragNormTable; + + + //-------------------------------------------------------------------------------------------------- + // Methods + //-------------------------------------------------------------------------------------------------- + + public: + double CalcPower(double speed, double acc, double gradient); + + double CalcEngPower(double power); + + double GetEmission(const std::string& pollutant, double power, double speed, Helpers* VehicleClass); + + + double GetCO2Emission(double _FC, double _CO, double _HC, Helpers* VehicleClass); + + double GetDecelCoast(double speed, double acc, double gradient); + + double GetRotationalCoeffecient(double speed); + + + private: + void FindLowerUpperInPattern(int& lowerIndex, int& upperIndex, std::vector& pattern, double value); + + double Interpolate(double px, double p1, double p2, double e1, double e2); + + public: + double GetMaxAccel(double speed, double gradient); + + private: + double GetPMaxNorm(double speed); + + //-------------------------------------------------------------------------------------------------- + // Operators for fleetmix + //-------------------------------------------------------------------------------------------------- + + + private: + void InitializeInstanceFields(); + }; +} + + +#endif //#ifndef PHEMlightCEP diff --git a/src/PHEMlight/CEPHandler.cpp b/src/PHEMlight/CEPHandler.cpp new file mode 100644 index 0000000..5fd4ec9 --- /dev/null +++ b/src/PHEMlight/CEPHandler.cpp @@ -0,0 +1,383 @@ +/****************************************************************************/ +// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo +// Copyright (C) 2016-2021 German Aerospace Center (DLR) and others. +// PHEMlight module +// Copyright 2016 Technische Universitaet Graz, https://www.tugraz.at/ +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0/ +// This Source Code may also be made available under the following Secondary +// Licenses when the conditions for such availability set forth in the Eclipse +// Public License 2.0 are satisfied: GNU General Public License, version 2 +// or later which is available at +// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html +// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later +/****************************************************************************/ +/// @file CEPHandler.cpp +/// @author Martin Dippold +/// @author Michael Behrisch +/// @date July 2016 +/// +// +/****************************************************************************/ + + +#include +#include +#include "CEPHandler.h" +#include "CEP.h" +#include "Helpers.h" +#include "Constants.h" + + +namespace PHEMlightdll { + + CEPHandler::CEPHandler() { + _ceps = std::map(); + } + + const std::map& CEPHandler::getCEPS() const { + return _ceps; + } + + bool CEPHandler::GetCEP(const std::vector& DataPath, Helpers* Helper) { + if (getCEPS().find(Helper->getgClass()) == getCEPS().end()) { + if (!Load(DataPath, Helper)) { + return false; + } + } + return true; + } + + bool CEPHandler::Load(const std::vector& DataPath, Helpers* Helper) { + //Deklaration + // get string identifier for PHEM emission class +//C# TO C++ CONVERTER TODO TASK: There is no native C++ equivalent to 'ToString': + std::string emissionRep = Helper->getgClass(); + + // to hold everything. + std::vector > matrixSpeedInertiaTable; + std::vector > normedTragTableSpeedInertiaTable; + std::vector > matrixFC; + std::vector > matrixPollutants; + std::vector idlingValuesFC; + std::vector idlingValuesPollutants; + std::vector headerFC; + std::vector headerPollutants; + + double vehicleMass; + double vehicleLoading; + double vehicleMassRot; + double crosssectionalArea; + double cwValue; + double f0; + double f1; + double f2; + double f3; + double f4; + double axleRatio; + std::vector transmissionGearRatios; + double auxPower; + double ratedPower; + double engineIdlingSpeed; + double engineRatedSpeed; + double effectiveWhellDiameter; + std::string vehicleMassType; + std::string vehicleFuelType; + double pNormV0; + double pNormP0; + double pNormV1; + double pNormP1; + + if (!ReadVehicleFile(DataPath, emissionRep, Helper, vehicleMass, vehicleLoading, vehicleMassRot, crosssectionalArea, cwValue, f0, f1, f2, f3, f4, axleRatio, auxPower, ratedPower, engineIdlingSpeed, engineRatedSpeed, effectiveWhellDiameter, transmissionGearRatios, vehicleMassType, vehicleFuelType, pNormV0, pNormP0, pNormV1, pNormP1, matrixSpeedInertiaTable, normedTragTableSpeedInertiaTable)) { + return false; + } + + if (!ReadEmissionData(true, DataPath, emissionRep, Helper, headerFC, matrixFC, idlingValuesFC)) { + return false; + } + + if (!ReadEmissionData(false, DataPath, emissionRep, Helper, headerPollutants, matrixPollutants, idlingValuesPollutants)) { + return false; + } + + _ceps.insert(std::make_pair(Helper->getgClass(), new CEP(vehicleMassType == Constants::HeavyVehicle, vehicleMass, vehicleLoading, vehicleMassRot, crosssectionalArea, cwValue, f0, f1, f2, f3, f4, axleRatio, transmissionGearRatios, auxPower, ratedPower, engineIdlingSpeed, engineRatedSpeed, effectiveWhellDiameter, pNormV0, pNormP0, pNormV1, pNormP1, vehicleFuelType, matrixFC, headerPollutants, matrixPollutants, matrixSpeedInertiaTable, normedTragTableSpeedInertiaTable, idlingValuesFC.front(), idlingValuesPollutants))); + + return true; + } + + bool CEPHandler::ReadVehicleFile(const std::vector& DataPath, const std::string& emissionClass, Helpers* Helper, double& vehicleMass, double& vehicleLoading, double& vehicleMassRot, double& crossArea, double& cWValue, double& f0, double& f1, double& f2, double& f3, double& f4, double& axleRatio, double& auxPower, double& ratedPower, double& engineIdlingSpeed, double& engineRatedSpeed, double& effectiveWheelDiameter, std::vector& transmissionGearRatios, std::string& vehicleMassType, std::string& vehicleFuelType, double& pNormV0, double& pNormP0, double& pNormV1, double& pNormP1, std::vector >& matrixSpeedInertiaTable, std::vector >& normedDragTable) { + vehicleMass = 0; + vehicleLoading = 0; + vehicleMassRot = 0; + crossArea = 0; + cWValue = 0; + f0 = 0; + f1 = 0; + f2 = 0; + f3 = 0; + f4 = 0; + axleRatio = 0; + ratedPower = 0; + auxPower = 0; + engineIdlingSpeed = 0; + engineRatedSpeed = 0; + effectiveWheelDiameter = 0; + vehicleMassType = ""; + vehicleFuelType = ""; + pNormV0 = 0; + pNormP0 = 0; + pNormV1 = 0; + pNormP1 = 0; + transmissionGearRatios = std::vector(); + matrixSpeedInertiaTable = std::vector >(); + normedDragTable = std::vector >(); + std::string line; + std::string cell; + int dataCount = 0; + + //Open file + std::ifstream vehicleReader; + for (std::vector::const_iterator i = DataPath.begin(); i != DataPath.end(); i++) { + vehicleReader.open(((*i) + emissionClass + ".PHEMLight.veh").c_str()); + if (vehicleReader.good()) { + break; + } + } + if (!vehicleReader.good()) { + Helper->setErrMsg("File does not exist! (" + emissionClass + ".PHEMLight.veh)"); + return false; + } + + // skip header + ReadLine(vehicleReader); + + while ((line = ReadLine(vehicleReader)) != "" && dataCount <= 49) { + if (line.substr(0, 1) == Helper->getCommentPrefix()) { + continue; + } + else { + dataCount++; + } + + cell = split(line, ',')[0]; + + // reading Mass + if (dataCount == 1) { + vehicleMass = todouble(cell); + } + + // reading vehicle loading + if (dataCount == 2) { + vehicleLoading = todouble(cell); + } + + // reading cWValue + if (dataCount == 3) { + cWValue = todouble(cell); + } + + // reading crossectional area + if (dataCount == 4) { + crossArea = todouble(cell); + } + + // reading vehicle mass rotational + if (dataCount == 7) { + vehicleMassRot = todouble(cell); + } + + // reading rated power + if (dataCount == 9) { + auxPower = todouble(cell); + } + + // reading rated power + if (dataCount == 10) { + ratedPower = todouble(cell); + } + + // reading engine rated speed + if (dataCount == 11) { + engineRatedSpeed = todouble(cell); + } + + // reading engine idling speed + if (dataCount == 12) { + engineIdlingSpeed = todouble(cell); + } + + // reading f0 + if (dataCount == 14) { + f0 = todouble(cell); + } + + // reading f1 + if (dataCount == 15) { + f1 = todouble(cell); + } + + // reading f2 + if (dataCount == 16) { + f2 = todouble(cell); + } + + // reading f3 + if (dataCount == 17) { + f3 = todouble(cell); + } + + // reading f4 + if (dataCount == 18) { + f4 = todouble(cell); + } + + // reading axleRatio + if (dataCount == 21) { + axleRatio = todouble(cell); + } + + // reading effective wheel diameter + if (dataCount == 22) { + effectiveWheelDiameter = todouble(cell); + } + + if (dataCount >= 23 && dataCount <= 40) { + transmissionGearRatios.push_back(todouble(cell)); + } + + // reading vehicleMassType + if (dataCount == 45) { + vehicleMassType = cell; + } + + // reading vehicleFuelType + if (dataCount == 46) { + vehicleFuelType = cell; + } + + // reading pNormV0 + if (dataCount == 47) { + pNormV0 = todouble(cell); + } + + // reading pNormP0 + if (dataCount == 48) { + pNormP0 = todouble(cell); + } + + // reading pNormV1 + if (dataCount == 49) { + pNormV1 = todouble(cell); + } + + // reading pNormP1 + if (dataCount == 50) { + pNormP1 = todouble(cell); + } + } + + while ((line = ReadLine(vehicleReader)) != "" && line.substr(0, 1) != Helper->getCommentPrefix()) { + if (line.substr(0, 1) == Helper->getCommentPrefix()) { + continue; + } + + matrixSpeedInertiaTable.push_back(todoubleList(split(line, ','))); + } + + while ((line = ReadLine(vehicleReader)) != "") { + if (line.substr(0, 1) == Helper->getCommentPrefix()) { + continue; + } + + normedDragTable.push_back(todoubleList(split(line, ','))); + } + + return true; + } + + bool CEPHandler::ReadEmissionData(bool readFC, const std::vector& DataPath, const std::string& emissionClass, Helpers* Helper, std::vector& header, std::vector >& matrix, std::vector& idlingValues) { + // declare file stream + std::string line; + header = std::vector(); + matrix = std::vector >(); + idlingValues = std::vector(); + + std::string pollutantExtension = ""; + if (readFC) { + pollutantExtension += std::string("_FC"); + } + + std::ifstream fileReader; + for (std::vector::const_iterator i = DataPath.begin(); i != DataPath.end(); i++) { + fileReader.open(((*i) + emissionClass + pollutantExtension + ".csv").c_str()); + if (fileReader.good()) { + break; + } + } + if (!fileReader.good()) { + Helper->setErrMsg("File does not exist! (" + emissionClass + pollutantExtension + ".csv)"); + return false; + } + + // read header line for pollutant identifiers + if ((line = ReadLine(fileReader)) != "") { + std::vector entries = split(line, ','); + // skip first entry "Pe" + for (int i = 1; i < (int)entries.size(); i++) { + header.push_back(entries[i]); + } + } + + // skip units + ReadLine(fileReader); + + // skip comment + ReadLine(fileReader); + + //readIdlingValues + line = ReadLine(fileReader); + + std::vector stringIdlings = split(line, ','); + stringIdlings.erase(stringIdlings.begin()); + + idlingValues = todoubleList(stringIdlings); + + while ((line = ReadLine(fileReader)) != "") { + matrix.push_back(todoubleList(split(line, ','))); + } + return true; + } + + std::vector CEPHandler::split(const std::string& s, char delim) { + std::vector elems; + std::stringstream ss(s); + std::string item; + while (std::getline(ss, item, delim)) { + elems.push_back(item); + } + return elems; + } + + double CEPHandler::todouble(const std::string& s) { + std::stringstream ss(s); + double item; + ss >> item; + return item; + } + + std::vector CEPHandler::todoubleList(const std::vector& s) { + std::vector result; + for (std::vector::const_iterator i = s.begin(); i != s.end(); ++i) { + result.push_back(todouble(*i)); + } + return result; + } + + std::string CEPHandler::ReadLine(std::ifstream& s) { + std::string line; + std::getline(s, line); + line.erase(line.find_last_not_of(" \n\r\t") + 1); + return line; + } +} diff --git a/src/PHEMlight/CEPHandler.h b/src/PHEMlight/CEPHandler.h new file mode 100644 index 0000000..91e8405 --- /dev/null +++ b/src/PHEMlight/CEPHandler.h @@ -0,0 +1,95 @@ +/****************************************************************************/ +// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo +// Copyright (C) 2016-2021 German Aerospace Center (DLR) and others. +// PHEMlight module +// Copyright 2016 Technische Universitaet Graz, https://www.tugraz.at/ +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0/ +// This Source Code may also be made available under the following Secondary +// Licenses when the conditions for such availability set forth in the Eclipse +// Public License 2.0 are satisfied: GNU General Public License, version 2 +// or later which is available at +// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html +// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later +/****************************************************************************/ +/// @file CEPHandler.h +/// @author Martin Dippold +/// @author Michael Behrisch +/// @date July 2016 +/// +// +/****************************************************************************/ + + +#ifndef PHEMlightCEPHANDLER +#define PHEMlightCEPHANDLER + +#include +#include +#include +#include + +//C# TO C++ CONVERTER NOTE: Forward class declarations: +namespace PHEMlightdll { class CEP; } +namespace PHEMlightdll { class Helpers; } + + +namespace PHEMlightdll { + class CEPHandler { + //-------------------------------------------------------------------------------------------------- + // Constructors + //-------------------------------------------------------------------------------------------------- + + public: + CEPHandler(); + + //-------------------------------------------------------------------------------------------------- + // Members + //-------------------------------------------------------------------------------------------------- + + private: + std::map _ceps; + public: + const std::map& getCEPS() const; + + + //-------------------------------------------------------------------------------------------------- + // Methods + //-------------------------------------------------------------------------------------------------- + + bool GetCEP(const std::vector& DataPath, Helpers* Helper); + + + //-------------------------------------------------------------------------------------------------- + // Methods + //-------------------------------------------------------------------------------------------------- + + private: + bool Load(const std::vector& DataPath, Helpers* Helper); + + bool ReadVehicleFile(const std::vector& DataPath, const std::string& emissionClass, Helpers* Helper, double& vehicleMass, double& vehicleLoading, double& vehicleMassRot, double& crossArea, double& cWValue, double& f0, double& f1, double& f2, double& f3, double& f4, double& axleRatio, double& auxPower, double& ratedPower, double& engineIdlingSpeed, double& engineRatedSpeed, double& effectiveWheelDiameter, std::vector& transmissionGearRatios, std::string& vehicleMassType, std::string& vehicleFuelType, double& pNormV0, double& pNormP0, double& pNormV1, double& pNormP1, std::vector >& matrixSpeedInertiaTable, std::vector >& normedDragTable); + + bool ReadEmissionData(bool readFC, const std::vector& DataPath, const std::string& emissionClass, Helpers* Helper, std::vector& header, std::vector >& matrix, std::vector& idlingValues); + + + //-------------------------------------------------------------------------------------------------- + // Functions + //-------------------------------------------------------------------------------------------------- + + //Split the string + std::vector split(const std::string& s, char delim); + + //Convert string to double + double todouble(const std::string& s); + + //Convert string to double list + std::vector todoubleList(const std::vector& s); + + //Read a line from file + std::string ReadLine(std::ifstream& s); + }; +} + + +#endif //#ifndef PHEMlightCEPHANDLER diff --git a/src/PHEMlight/CMakeLists.txt b/src/PHEMlight/CMakeLists.txt new file mode 100644 index 0000000..126370d --- /dev/null +++ b/src/PHEMlight/CMakeLists.txt @@ -0,0 +1,13 @@ +set(foreign_phemlight_STAT_SRCS + CEP.cpp + CEP.h + CEPHandler.cpp + CEPHandler.h + Constants.cpp + Constants.h + Helpers.cpp + Helpers.h +) + +add_library(foreign_phemlight STATIC ${foreign_phemlight_STAT_SRCS}) +set_property(TARGET foreign_phemlight PROPERTY PROJECT_LABEL "z_foreign_phemlight") diff --git a/src/PHEMlight/Constants.cpp b/src/PHEMlight/Constants.cpp new file mode 100644 index 0000000..fdafdc3 --- /dev/null +++ b/src/PHEMlight/Constants.cpp @@ -0,0 +1,67 @@ +/****************************************************************************/ +// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo +// Copyright (C) 2016-2021 German Aerospace Center (DLR) and others. +// PHEMlight module +// Copyright (C) 2016-2017 Technische Universitaet Graz, https://www.tugraz.at/ +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0/ +// This Source Code may also be made available under the following Secondary +// Licenses when the conditions for such availability set forth in the Eclipse +// Public License 2.0 are satisfied: GNU General Public License, version 2 +// or later which is available at +// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html +// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later +/****************************************************************************/ +/// @file Constants.cpp +/// @author Martin Dippold +/// @author Michael Behrisch +/// @date July 2016 +/// +// +/****************************************************************************/ + + +#include "Constants.h" + + +namespace PHEMlightdll { + +const double Constants::GRAVITY_CONST = 9.81; +const double Constants::AIR_DENSITY_CONST = 1.182; +const double Constants::NORMALIZING_SPEED = 19.444; +const double Constants::NORMALIZING_ACCELARATION = 0.45; +const double Constants::SPEED_DCEL_MIN = 10 / 3.6; +const double Constants::ZERO_SPEED_ACCURACY = 0.5; +const double Constants::DRIVE_TRAIN_EFFICIENCY_All = 0.9; +const double Constants::DRIVE_TRAIN_EFFICIENCY_CB = 0.8; +const std::string Constants::HeavyVehicle = "HV"; +const std::string Constants::strPKW = "PC"; +const std::string Constants::strLNF = "LCV"; +const std::string Constants::strLKW = "HDV_RT"; +const std::string Constants::strLSZ = "HDV_TT"; +const std::string Constants::strRB = "HDV_CO"; +const std::string Constants::strLB = "HDV_CB"; +const std::string Constants::strMR2 = "MC_2S"; +const std::string Constants::strMR4 = "MC_4S"; +const std::string Constants::strKKR = "MOP"; +const std::string Constants::strGasoline = "G"; +const std::string Constants::strDiesel = "D"; +const std::string Constants::strCNG = "CNG"; +const std::string Constants::strLPG = "LPG"; +const std::string Constants::strHybrid = "HEV"; +const std::string Constants::strBEV = "BEV"; +const std::string Constants::strEU = "EU"; +const std::string Constants::strSI = "I"; +const std::string Constants::strSII = "II"; +const std::string Constants::strSIII = "III"; +double Constants::_DRIVE_TRAIN_EFFICIENCY = 0; + + const double& Constants::getDRIVE_TRAIN_EFFICIENCY() { + return _DRIVE_TRAIN_EFFICIENCY; + } + + void Constants::setDRIVE_TRAIN_EFFICIENCY(const double& value) { + _DRIVE_TRAIN_EFFICIENCY = value; + } +} diff --git a/src/PHEMlight/Constants.h b/src/PHEMlight/Constants.h new file mode 100644 index 0000000..cf0e9da --- /dev/null +++ b/src/PHEMlight/Constants.h @@ -0,0 +1,86 @@ +/****************************************************************************/ +// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo +// Copyright (C) 2016-2021 German Aerospace Center (DLR) and others. +// PHEMlight module +// Copyright (C) 2016-2017 Technische Universitaet Graz, https://www.tugraz.at/ +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0/ +// This Source Code may also be made available under the following Secondary +// Licenses when the conditions for such availability set forth in the Eclipse +// Public License 2.0 are satisfied: GNU General Public License, version 2 +// or later which is available at +// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html +// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later +/****************************************************************************/ +/// @file Constants.h +/// @author Martin Dippold +/// @author Michael Behrisch +/// @date July 2016 +/// +// +/****************************************************************************/ + + +#ifndef PHEMlightCONSTANTS +#define PHEMlightCONSTANTS + +#include + +#define FLEET + +namespace PHEMlightdll { + class Constants { + //Calculation constant + public: + static const double GRAVITY_CONST; + static const double AIR_DENSITY_CONST; + static const double NORMALIZING_SPEED; + static const double NORMALIZING_ACCELARATION; + static const double SPEED_DCEL_MIN; + static const double ZERO_SPEED_ACCURACY; + static const double DRIVE_TRAIN_EFFICIENCY_All; + static const double DRIVE_TRAIN_EFFICIENCY_CB; + + + //Strings + static const std::string HeavyVehicle; + + //Vehiclestrings + static const std::string strPKW; + static const std::string strLNF; + static const std::string strLKW; + static const std::string strLSZ; + static const std::string strRB; + static const std::string strLB; + static const std::string strMR2; + static const std::string strMR4; + static const std::string strKKR; + + //Fuelstrings + static const std::string strGasoline; + static const std::string strDiesel; + static const std::string strCNG; + static const std::string strLPG; + static const std::string strHybrid; + static const std::string strBEV; + + //Euroclasses + static const std::string strEU; + + //Sizeclasse + static const std::string strSI; + static const std::string strSII; + static const std::string strSIII; + + + //Drive train efficiency + static double _DRIVE_TRAIN_EFFICIENCY; + const static double& getDRIVE_TRAIN_EFFICIENCY(); + static void setDRIVE_TRAIN_EFFICIENCY(const double& value); + + }; +} + + +#endif //#ifndef PHEMlightCONSTANTS diff --git a/src/PHEMlight/Helpers.cpp b/src/PHEMlight/Helpers.cpp new file mode 100644 index 0000000..f6640ea --- /dev/null +++ b/src/PHEMlight/Helpers.cpp @@ -0,0 +1,272 @@ +/****************************************************************************/ +// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo +// Copyright (C) 2016-2021 German Aerospace Center (DLR) and others. +// PHEMlight module +// Copyright 2016 Technische Universitaet Graz, https://www.tugraz.at/ +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0/ +// This Source Code may also be made available under the following Secondary +// Licenses when the conditions for such availability set forth in the Eclipse +// Public License 2.0 are satisfied: GNU General Public License, version 2 +// or later which is available at +// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html +// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later +/****************************************************************************/ +/// @file Helpers.cpp +/// @author Martin Dippold +/// @author Michael Behrisch +/// @date July 2016 +/// +// +/****************************************************************************/ + + +#include "Helpers.h" +#include "Constants.h" + + +namespace PHEMlightdll { + + const std::string& Helpers::getvClass() const { + return _vClass; + } + + void Helpers::setvClass(const std::string& value) { + _vClass = value; + } + + const std::string& Helpers::geteClass() const { + return _eClass; + } + + void Helpers::seteClass(const std::string& value) { + _eClass = value; + } + + const std::string& Helpers::gettClass() const { + return _tClass; + } + + void Helpers::settClass(const std::string& value) { + _tClass = value; + } + + const std::string& Helpers::getsClass() const { + return _sClass; + } + + void Helpers::setsClass(const std::string& value) { + _sClass = value; + } + + const std::string& Helpers::getgClass() const { + return _Class; + } + + void Helpers::setgClass(const std::string& value) { + _Class = value; + } + + const std::string& Helpers::getErrMsg() const { + return _ErrMsg; + } + + void Helpers::setErrMsg(const std::string& value) { + _ErrMsg = value; + } + + const std::string& Helpers::getCommentPrefix() const { + return _commentPrefix; + } + + void Helpers::setCommentPrefix(const std::string& value) { + _commentPrefix = value; + } + + const std::string& Helpers::getPHEMDataV() const { + return _PHEMDataV; + } + + void Helpers::setPHEMDataV(const std::string& value) { + _PHEMDataV = value; + } + + bool Helpers::getvclass(const std::string& VEH) { + // Set the drive train efficency + Constants::setDRIVE_TRAIN_EFFICIENCY(Constants::DRIVE_TRAIN_EFFICIENCY_All); + + //Get the vehicle class + if (VEH.find(Constants::strPKW) != std::string::npos) { + _vClass = Constants::strPKW; + return true; + } + else if (VEH.find(Constants::strLNF) != std::string::npos) { + _vClass = Constants::strLNF; + return true; + } + else if (VEH.find(Constants::strLKW) != std::string::npos) { + _vClass = Constants::strLKW; + return true; + } + else if (VEH.find(Constants::strLSZ) != std::string::npos) { + _vClass = Constants::strLSZ; + return true; + } + else if (VEH.find(Constants::strRB) != std::string::npos) { + _vClass = Constants::strRB; + return true; + } + else if (VEH.find(Constants::strLB) != std::string::npos) { + _vClass = Constants::strLB; + Constants::setDRIVE_TRAIN_EFFICIENCY(Constants::DRIVE_TRAIN_EFFICIENCY_CB); + return true; + } + else if (VEH.find(Constants::strMR2) != std::string::npos) { + _vClass = Constants::strMR2; + return true; + } + else if (VEH.find(Constants::strMR4) != std::string::npos) { + _vClass = Constants::strMR4; + return true; + } + else if (VEH.find(Constants::strKKR) != std::string::npos) { + _vClass = Constants::strKKR; + return true; + } + //Should never happens + _ErrMsg = std::string("Vehicle class not defined! (") + VEH + std::string(")"); + return false; + } + + bool Helpers::gettclass(const std::string& VEH) { + if ((int)VEH.find(std::string("_") + Constants::strDiesel) > 0) { + if ((int)VEH.find(std::string("_") + Constants::strHybrid) > 0) { + _tClass = Constants::strDiesel + std::string("_") + Constants::strHybrid; + return true; + } + else { + _tClass = Constants::strDiesel; + return true; + } + + } + else if ((int)VEH.find(std::string("_") + Constants::strGasoline) > 0) { + if ((int)VEH.find(std::string("_") + Constants::strHybrid) > 0) { + _tClass = Constants::strGasoline + std::string("_") + Constants::strHybrid; + return true; + } + else { + _tClass = Constants::strGasoline; + return true; + } + } + else if ((int)VEH.find(std::string("_") + Constants::strCNG) > 0) { + _tClass = Constants::strCNG; + return true; + } + else if ((int)VEH.find(std::string("_") + Constants::strBEV) > 0) { + _tClass = Constants::strBEV; + return true; + } + //Should never happens + _ErrMsg = std::string("Fuel class not defined! (") + VEH + std::string(")"); + return false; + } + + bool Helpers::getsclass(const std::string& VEH) { + if (VEH.find(Constants::strLKW) != std::string::npos) { + if ((int)VEH.find(std::string("_") + Constants::strSII) > 0) { + _sClass = Constants::strSII; + return true; + } + else if ((int)VEH.find(std::string("_") + Constants::strSI) > 0) { + _sClass = Constants::strSI; + return true; + } + else { + //Should never happen + _ErrMsg = std::string("Size class not defined! (") + VEH + std::string(")"); + return false; + } + } + else if (VEH.find(Constants::strLNF) != std::string::npos) { + if ((int)VEH.find(std::string("_") + Constants::strSIII) > 0) { + _sClass = Constants::strSIII; + return true; + } + else if ((int)VEH.find(std::string("_") + Constants::strSII) > 0) { + _sClass = Constants::strSII; + return true; + } + else if ((int)VEH.find(std::string("_") + Constants::strSI) > 0) { + _sClass = Constants::strSI; + return true; + } + else { + _ErrMsg = std::string("Size class not defined! (") + VEH.substr((int)VEH.rfind("\\"), VEH.length() - (int)VEH.rfind("\\")) + std::string(")"); + return false; + } + } + else { + _sClass = ""; + return true; + } + } + + bool Helpers::geteclass(const std::string& VEH) { + if ((int)VEH.find(std::string("_") + Constants::strEU) > 0) { + if ((int)VEH.find("_", (int)VEH.find(std::string("_") + Constants::strEU) + 1) > 0) { + _eClass = Constants::strEU + VEH.substr((int)VEH.find(std::string("_") + Constants::strEU) + 3, (int)VEH.find("_", (int)VEH.find(std::string("_") + Constants::strEU) + 1) - ((int)VEH.find(std::string("_") + Constants::strEU) + 3)); + return true; + } + else if ((int)VEH.find(".", (int)VEH.find(std::string("_") + Constants::strEU) + 1) > 0) { + _eClass = Constants::strEU + VEH.substr((int)VEH.find(std::string("_") + Constants::strEU) + 3, (int)VEH.find(".", (int)VEH.find(std::string("_") + Constants::strEU) + 1) - ((int)VEH.find(std::string("_") + Constants::strEU) + 3)); + return true; + } + else { + _eClass = Constants::strEU + VEH.substr((int)VEH.find(std::string("_") + Constants::strEU) + 3, VEH.length() - ((int)VEH.find(std::string("_") + Constants::strEU) + 3)); + return true; + } + } + else if ((int)VEH.find(std::string("_") + Constants::strBEV) > 0) { + _eClass = ""; + return true; + } + //Should never happens + _ErrMsg = std::string("Euro class not defined! (") + VEH + std::string(")"); + return false; + } + + bool Helpers::setclass(const std::string& VEH) { + if (getvclass(VEH)) { + _Class = _vClass; + } + else { + return false; + } + if (getsclass(VEH)) { + if (_sClass != "") { + _Class = _Class + std::string("_") + getsClass(); + } + } + else { + return false; + } + if (gettclass(VEH)) { + _Class = _Class + std::string("_") + gettClass(); + } + else { + return false; + } + if (geteclass(VEH)) { + if (_eClass != "") { + _Class = _Class + std::string("_") + geteClass(); + } + } + else { + return false; + } + return true; + } +} diff --git a/src/PHEMlight/Helpers.h b/src/PHEMlight/Helpers.h new file mode 100644 index 0000000..ce25e6c --- /dev/null +++ b/src/PHEMlight/Helpers.h @@ -0,0 +1,99 @@ +/****************************************************************************/ +// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo +// Copyright (C) 2016-2021 German Aerospace Center (DLR) and others. +// PHEMlight module +// Copyright 2016 Technische Universitaet Graz, https://www.tugraz.at/ +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0/ +// This Source Code may also be made available under the following Secondary +// Licenses when the conditions for such availability set forth in the Eclipse +// Public License 2.0 are satisfied: GNU General Public License, version 2 +// or later which is available at +// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html +// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later +/****************************************************************************/ +/// @file Helpers.h +/// @author Martin Dippold +/// @author Michael Behrisch +/// @date July 2016 +/// +// +/****************************************************************************/ + + +#ifndef PHEMlightHELPERS +#define PHEMlightHELPERS + +#include + + +namespace PHEMlightdll { + class Helpers { + //-------------------------------------------------------------------------------------------------- + // Members + //-------------------------------------------------------------------------------------------------- + private: + std::string _vClass; + public: + const std::string& getvClass() const; + void setvClass(const std::string& value); + private: + std::string _eClass; + public: + const std::string& geteClass() const; + void seteClass(const std::string& value); + private: + std::string _tClass; + public: + const std::string& gettClass() const; + void settClass(const std::string& value); + private: + std::string _sClass; + public: + const std::string& getsClass() const; + void setsClass(const std::string& value); + private: + std::string _Class; + public: + const std::string& getgClass() const; + void setgClass(const std::string& value); + private: + std::string _ErrMsg; + public: + const std::string& getErrMsg() const; + void setErrMsg(const std::string& value); + private: + std::string _commentPrefix; + public: + const std::string& getCommentPrefix() const; + void setCommentPrefix(const std::string& value); + private: + std::string _PHEMDataV; + public: + const std::string& getPHEMDataV() const; + void setPHEMDataV(const std::string& value); + + //Get vehicle class + private: + bool getvclass(const std::string& VEH); + + //Get technologie Class + bool gettclass(const std::string& VEH); + + //Get size class + bool getsclass(const std::string& VEH); + + //Get euro class + bool geteclass(const std::string& VEH); + + //Set complete class string + public: + bool setclass(const std::string& VEH); + + + }; +} + + +#endif //#ifndef PHEMlightHELPERS diff --git a/src/PHEMlight/README.md b/src/PHEMlight/README.md new file mode 100644 index 0000000..330c6c0 --- /dev/null +++ b/src/PHEMlight/README.md @@ -0,0 +1,3 @@ +# Origin + +Forked from [sumo](https://github.com/eclipse/sumo/tree/master/src/foreign/PHEMlight/cpp) diff --git a/src/PHEMlight/conversion.patch b/src/PHEMlight/conversion.patch new file mode 100644 index 0000000..5a729d8 --- /dev/null +++ b/src/PHEMlight/conversion.patch @@ -0,0 +1,573 @@ +diff --git b/src/foreign/PHEMlight/cpp/CEP.cpp a/src/foreign/PHEMlight/cpp/CEP.cpp +index eafe2e787f..5a0aef688e 100644 +--- b/src/foreign/PHEMlight/cpp/CEP.cpp ++++ a/src/foreign/PHEMlight/cpp/CEP.cpp +@@ -1,4 +1,25 @@ +-#include "CEP.h" ++/****************************************************************************/ ++// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo ++// Copyright (C) 2016-2018 German Aerospace Center (DLR) and others. ++// PHEMlight module ++// Copyright (C) 2016-2017 Technische Universitaet Graz, https://www.tugraz.at/ ++// This program and the accompanying materials ++// are made available under the terms of the Eclipse Public License v2.0 ++// which accompanies this distribution, and is available at ++// http://www.eclipse.org/legal/epl-v20.html ++// SPDX-License-Identifier: EPL-2.0 ++/****************************************************************************/ ++/// @file CEP.cpp ++/// @author Martin Dippold ++/// @author Michael Behrisch ++/// @date July 2016 ++/// @version $Id$ ++/// ++// ++/****************************************************************************/ ++ ++ ++#include "CEP.h" + #include "Constants.h" + #include "Helpers.h" + +@@ -6,6 +27,7 @@ + namespace PHEMlightdll { + + CEP::CEP(bool heavyVehicle, double vehicleMass, double vehicleLoading, double vehicleMassRot, double crossArea, double cWValue, double f0, double f1, double f2, double f3, double f4, double axleRatio, std::vector& transmissionGearRatios, double auxPower, double ratedPower, double engineIdlingSpeed, double engineRatedSpeed, double effictiveWheelDiameter, double pNormV0, double pNormP0, double pNormV1, double pNormP1, const std::string& vehicelFuelType, std::vector >& matrixFC, std::vector& headerLinePollutants, std::vector >& matrixPollutants, std::vector >& matrixSpeedRotational, std::vector >& normedDragTable, double idlingFC, std::vector& idlingPollutants) { ++ (void)transmissionGearRatios; // just to make the compiler happy about the unused parameter + InitializeInstanceFields(); + _resistanceF0 = f0; + _resistanceF1 = f1; +@@ -36,12 +58,12 @@ namespace PHEMlightdll { + std::vector > normalizedPollutantMeasures; + + // init pollutant identifiers +- for (int i = 0; i < headerLinePollutants.size(); i++) { ++ for (int i = 0; i < (int)headerLinePollutants.size(); i++) { + pollutantIdentifier.push_back(headerLinePollutants[i]); + } + + // initialize measures +- for (int i = 0; i < headerLinePollutants.size(); i++) { ++ for (int i = 0; i < (int)headerLinePollutants.size(); i++) { + pollutantMeasures.push_back(std::vector()); + normalizedPollutantMeasures.push_back(std::vector()); + } +@@ -50,7 +72,7 @@ namespace PHEMlightdll { + _speedCurveRotational = std::vector(); + _speedPatternRotational = std::vector(); + _gearTransmissionCurve = std::vector(); +- for (int i = 0; i < matrixSpeedRotational.size(); i++) { ++ for (int i = 0; i < (int)matrixSpeedRotational.size(); i++) { + if (matrixSpeedRotational[i].size() != 3) { + return; + } +@@ -63,7 +85,7 @@ namespace PHEMlightdll { + // looping through matrix and assigning values for drag table + _nNormTable = std::vector(); + _dragNormTable = std::vector(); +- for (int i = 0; i < normedDragTable.size(); i++) { ++ for (int i = 0; i < (int)normedDragTable.size(); i++) { + if (normedDragTable[i].size() != 2) { + return; + } +@@ -77,7 +99,7 @@ namespace PHEMlightdll { + _normedCepCurveFC = std::vector(); + _powerPatternFC = std::vector(); + _normalizedPowerPatternFC = std::vector(); +- for (int i = 0; i < matrixFC.size(); i++) { ++ for (int i = 0; i < (int)matrixFC.size(); i++) { + if (matrixFC[i].size() != 2) { + return; + } +@@ -110,10 +132,10 @@ namespace PHEMlightdll { + + _cepNormalizedCurvePollutants = std::map >(); + +- int headerCount = headerLinePollutants.size(); +- for (int i = 0; i < matrixPollutants.size(); i++) { +- for (int j = 0; j < matrixPollutants[i].size(); j++) { +- if (matrixPollutants[i].size() != headerCount + 1) { ++ int headerCount = (int)headerLinePollutants.size(); ++ for (int i = 0; i < (int)matrixPollutants.size(); i++) { ++ for (int j = 0; j < (int)matrixPollutants[i].size(); j++) { ++ if ((int)matrixPollutants[i].size() != headerCount + 1) { + return; + } + +@@ -131,7 +153,7 @@ namespace PHEMlightdll { + _cepCurvePollutants = std::map >(); + _idlingValuesPollutants = std::map(); + +- for (int i = 0; i < headerLinePollutants.size(); i++) { ++ for (int i = 0; i < (int)headerLinePollutants.size(); i++) { + _cepCurvePollutants.insert(std::make_pair(pollutantIdentifier[i], pollutantMeasures[i])); + _cepNormalizedCurvePollutants.insert(std::make_pair(pollutantIdentifier[i], normalizedPollutantMeasures[i])); + _idlingValuesPollutants.insert(std::make_pair(pollutantIdentifier[i], idlingPollutants[i] * pollutantMultiplyer)); +@@ -211,7 +233,7 @@ namespace PHEMlightdll { + int upperIndex; + int lowerIndex; + +- if (VehicleClass->gettClass() != Constants::strBEV) { ++ if (_fuelType != Constants::strBEV) { + if (std::abs(speed) <= Constants::ZERO_SPEED_ACCURACY) { + if (pollutant == "FC") { + return _idlingValueFC; +@@ -353,14 +375,14 @@ namespace PHEMlightdll { + } + + if (value >= pattern.back()) { +- lowerIndex = pattern.size() - 1; +- upperIndex = pattern.size() - 1; ++ lowerIndex = (int)pattern.size() - 1; ++ upperIndex = (int)pattern.size() - 1; + return; + } + + // bisection search to find correct position in power pattern +- int middleIndex = (pattern.size() - 1) / 2; +- upperIndex = pattern.size() - 1; ++ int middleIndex = ((int)pattern.size() - 1) / 2; ++ upperIndex = (int)pattern.size() - 1; + lowerIndex = 0; + + while (upperIndex - lowerIndex > 1) { +diff --git b/src/foreign/PHEMlight/cpp/CEP.h a/src/foreign/PHEMlight/cpp/CEP.h +index f24983953b..84aa342689 100644 +--- b/src/foreign/PHEMlight/cpp/CEP.h ++++ a/src/foreign/PHEMlight/cpp/CEP.h +@@ -1,4 +1,25 @@ +-#ifndef PHEMlightCEP ++/****************************************************************************/ ++// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo ++// Copyright (C) 2016-2018 German Aerospace Center (DLR) and others. ++// PHEMlight module ++// Copyright (C) 2016-2017 Technische Universitaet Graz, https://www.tugraz.at/ ++// This program and the accompanying materials ++// are made available under the terms of the Eclipse Public License v2.0 ++// which accompanies this distribution, and is available at ++// http://www.eclipse.org/legal/epl-v20.html ++// SPDX-License-Identifier: EPL-2.0 ++/****************************************************************************/ ++/// @file CEP.h ++/// @author Martin Dippold ++/// @author Michael Behrisch ++/// @date July 2016 ++/// @version $Id$ ++/// ++// ++/****************************************************************************/ ++ ++ ++#ifndef PHEMlightCEP + #define PHEMlightCEP + + #define _USE_MATH_DEFINES +@@ -11,7 +32,6 @@ + //C# TO C++ CONVERTER NOTE: Forward class declarations: + namespace PHEMlightdll { class Helpers; } + +-#define FLEET + + namespace PHEMlightdll { + class CEP { +diff --git b/src/foreign/PHEMlight/cpp/CEPHandler.cpp a/src/foreign/PHEMlight/cpp/CEPHandler.cpp +index 53a739894b..fa5ee8e2ae 100644 +--- b/src/foreign/PHEMlight/cpp/CEPHandler.cpp ++++ a/src/foreign/PHEMlight/cpp/CEPHandler.cpp +@@ -1,4 +1,27 @@ +-#include "CEPHandler.h" ++/****************************************************************************/ ++// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo ++// Copyright (C) 2016-2018 German Aerospace Center (DLR) and others. ++// PHEMlight module ++// Copyright 2016 Technische Universitaet Graz, https://www.tugraz.at/ ++// This program and the accompanying materials ++// are made available under the terms of the Eclipse Public License v2.0 ++// which accompanies this distribution, and is available at ++// http://www.eclipse.org/legal/epl-v20.html ++// SPDX-License-Identifier: EPL-2.0 ++/****************************************************************************/ ++/// @file CEPHandler.cpp ++/// @author Martin Dippold ++/// @author Michael Behrisch ++/// @date July 2016 ++/// @version $Id$ ++/// ++// ++/****************************************************************************/ ++ ++ ++#include ++#include ++#include "CEPHandler.h" + #include "CEP.h" + #include "Helpers.h" + #include "Constants.h" +@@ -10,11 +33,11 @@ namespace PHEMlightdll { + _ceps = std::map(); + } + +- std::map CEPHandler::getCEPS() const { ++ const std::map& CEPHandler::getCEPS() const { + return _ceps; + } + +- bool CEPHandler::GetCEP(const std::string& DataPath, Helpers* Helper) { ++ bool CEPHandler::GetCEP(const std::vector& DataPath, Helpers* Helper) { + if (getCEPS().find(Helper->getgClass()) == getCEPS().end()) { + if (!Load(DataPath, Helper)) { + return false; +@@ -23,11 +46,11 @@ namespace PHEMlightdll { + return true; + } + +- bool CEPHandler::Load(const std::string& DataPath, Helpers* Helper) { ++ bool CEPHandler::Load(const std::vector& DataPath, Helpers* Helper) { + //Deklaration + // get string identifier for PHEM emission class + //C# TO C++ CONVERTER TODO TASK: There is no native C++ equivalent to 'ToString': +- std::string emissionRep = Helper->getgClass().ToString(); ++ std::string emissionRep = Helper->getgClass(); + + // to hold everything. + std::vector > matrixSpeedInertiaTable; +@@ -80,7 +103,7 @@ namespace PHEMlightdll { + return true; + } + +- bool CEPHandler::ReadVehicleFile(const std::string& DataPath, const std::string& emissionClass, Helpers* Helper, double& vehicleMass, double& vehicleLoading, double& vehicleMassRot, double& crossArea, double& cWValue, double& f0, double& f1, double& f2, double& f3, double& f4, double& axleRatio, double& auxPower, double& ratedPower, double& engineIdlingSpeed, double& engineRatedSpeed, double& effectiveWheelDiameter, std::vector& transmissionGearRatios, std::string& vehicleMassType, std::string& vehicleFuelType, double& pNormV0, double& pNormP0, double& pNormV1, double& pNormP1, std::vector >& matrixSpeedInertiaTable, std::vector >& normedDragTable) { ++ bool CEPHandler::ReadVehicleFile(const std::vector& DataPath, const std::string& emissionClass, Helpers* Helper, double& vehicleMass, double& vehicleLoading, double& vehicleMassRot, double& crossArea, double& cWValue, double& f0, double& f1, double& f2, double& f3, double& f4, double& axleRatio, double& auxPower, double& ratedPower, double& engineIdlingSpeed, double& engineRatedSpeed, double& effectiveWheelDiameter, std::vector& transmissionGearRatios, std::string& vehicleMassType, std::string& vehicleFuelType, double& pNormV0, double& pNormP0, double& pNormV1, double& pNormP1, std::vector >& matrixSpeedInertiaTable, std::vector >& normedDragTable) { + vehicleMass = 0; + vehicleLoading = 0; + vehicleMassRot = 0; +@@ -111,12 +134,17 @@ namespace PHEMlightdll { + int dataCount = 0; + + //Open file +- std::string path = DataPath + std::string("\\") + emissionClass + std::string(".PHEMLight.veh"); +- if (!File::Exists(path)) { +- Helper->setErrMsg(std::string("File do not exist! (") + path + std::string(")")); ++ std::ifstream vehicleReader; ++ for (std::vector::const_iterator i = DataPath.begin(); i != DataPath.end(); i++) { ++ vehicleReader.open(((*i) + emissionClass + ".PHEMLight.veh").c_str()); ++ if (vehicleReader.good()) { ++ break; ++ } ++ } ++ if (!vehicleReader.good()) { ++ Helper->setErrMsg("File does not exist! (" + emissionClass + ".PHEMLight.veh)"); + return false; + } +- StreamReader* vehicleReader = File::OpenText(path); + + // skip header + ReadLine(vehicleReader); +@@ -262,11 +290,10 @@ namespace PHEMlightdll { + normedDragTable.push_back(todoubleList(split(line, ','))); + } + +- vehicleReader->Close(); + return true; + } + +- bool CEPHandler::ReadEmissionData(bool readFC, const std::string& DataPath, const std::string& emissionClass, Helpers* Helper, std::vector& header, std::vector >& matrix, std::vector& idlingValues) { ++ bool CEPHandler::ReadEmissionData(bool readFC, const std::vector& DataPath, const std::string& emissionClass, Helpers* Helper, std::vector& header, std::vector >& matrix, std::vector& idlingValues) { + // declare file stream + std::string line; + header = std::vector(); +@@ -278,18 +305,23 @@ namespace PHEMlightdll { + pollutantExtension += std::string("_FC"); + } + +- std::string path = DataPath + std::string("\\") + emissionClass + pollutantExtension + std::string(".csv"); +- if (!File::Exists(path)) { +- Helper->setErrMsg(std::string("File do not exist! (") + path + std::string(")")); ++ std::ifstream fileReader; ++ for (std::vector::const_iterator i = DataPath.begin(); i != DataPath.end(); i++) { ++ fileReader.open(((*i) + emissionClass + pollutantExtension + ".csv").c_str()); ++ if (fileReader.good()) { ++ break; ++ } ++ } ++ if (!fileReader.good()) { ++ Helper->setErrMsg("File does not exist! (" + emissionClass + pollutantExtension + ".csv)"); + return false; + } +- StreamReader* fileReader = File::OpenText(path); + + // read header line for pollutant identifiers + if ((line = ReadLine(fileReader)) != "") { +- std::vector& entries = split(line, ','); ++ std::vector entries = split(line, ','); + // skip first entry "Pe" +- for (int i = 1; i < entries.size(); i++) { ++ for (int i = 1; i < (int)entries.size(); i++) { + header.push_back(entries[i]); + } + } +@@ -303,7 +335,7 @@ namespace PHEMlightdll { + //readIdlingValues + line = ReadLine(fileReader); + +- std::vector stringIdlings = split(line, ',').ToList(); ++ std::vector stringIdlings = split(line, ','); + stringIdlings.erase(stringIdlings.begin()); + + idlingValues = todoubleList(stringIdlings); +@@ -311,26 +343,38 @@ namespace PHEMlightdll { + while ((line = ReadLine(fileReader)) != "") { + matrix.push_back(todoubleList(split(line, ','))); + } +- fileReader->Close(); + return true; + } + + std::vector CEPHandler::split(const std::string& s, char delim) { +-//C# TO C++ CONVERTER TODO TASK: There is no direct native C++ equivalent to this .NET String method: +- return s.Split(delim).ToList(); ++ std::vector elems; ++ std::stringstream ss(s); ++ std::string item; ++ while (std::getline(ss, item, delim)) { ++ elems.push_back(item); ++ } ++ return elems; + } + + double CEPHandler::todouble(const std::string& s) { +- return static_cast(s, CultureInfo::InvariantCulture); ++ std::stringstream ss(s); ++ double item; ++ ss >> item; ++ return item; + } + +- std::vector CEPHandler::todoubleList(std::vector& s) { +- return s.Select([&] (void* p) { +- todouble(p); +- }).Cast().ToList(); ++ std::vector CEPHandler::todoubleList(const std::vector& s) { ++ std::vector result; ++ for (std::vector::const_iterator i = s.begin(); i != s.end(); ++i) { ++ result.push_back(todouble(*i)); ++ } ++ return result; + } + +- std::string CEPHandler::ReadLine(StreamReader* s) { +- return s->ReadLine(); ++ std::string CEPHandler::ReadLine(std::ifstream& s) { ++ std::string line; ++ std::getline(s, line); ++ line.erase(line.find_last_not_of(" \n\r\t") + 1); ++ return line; + } + } +diff --git b/src/foreign/PHEMlight/cpp/CEPHandler.h a/src/foreign/PHEMlight/cpp/CEPHandler.h +index bd46d8d9b9..d2e0fd3fb6 100644 +--- b/src/foreign/PHEMlight/cpp/CEPHandler.h ++++ a/src/foreign/PHEMlight/cpp/CEPHandler.h +@@ -1,4 +1,25 @@ +-#ifndef PHEMlightCEPHANDLER ++/****************************************************************************/ ++// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo ++// Copyright (C) 2016-2018 German Aerospace Center (DLR) and others. ++// PHEMlight module ++// Copyright 2016 Technische Universitaet Graz, https://www.tugraz.at/ ++// This program and the accompanying materials ++// are made available under the terms of the Eclipse Public License v2.0 ++// which accompanies this distribution, and is available at ++// http://www.eclipse.org/legal/epl-v20.html ++// SPDX-License-Identifier: EPL-2.0 ++/****************************************************************************/ ++/// @file CEPHandler.h ++/// @author Martin Dippold ++/// @author Michael Behrisch ++/// @date July 2016 ++/// @version $Id$ ++/// ++// ++/****************************************************************************/ ++ ++ ++#ifndef PHEMlightCEPHANDLER + #define PHEMlightCEPHANDLER + + #include +@@ -10,7 +31,6 @@ + namespace PHEMlightdll { class CEP; } + namespace PHEMlightdll { class Helpers; } + +-#define FLEET + + namespace PHEMlightdll { + class CEPHandler { +@@ -28,14 +48,14 @@ namespace PHEMlightdll { + private: + std::map _ceps; + public: +- std::map getCEPS() const; ++ const std::map& getCEPS() const; + + + //-------------------------------------------------------------------------------------------------- + // Methods + //-------------------------------------------------------------------------------------------------- + +- bool GetCEP(const std::string& DataPath, Helpers* Helper); ++ bool GetCEP(const std::vector& DataPath, Helpers* Helper); + + + //-------------------------------------------------------------------------------------------------- +@@ -43,11 +63,11 @@ namespace PHEMlightdll { + //-------------------------------------------------------------------------------------------------- + + private: +- bool Load(const std::string& DataPath, Helpers* Helper); ++ bool Load(const std::vector& DataPath, Helpers* Helper); + +- bool ReadVehicleFile(const std::string& DataPath, const std::string& emissionClass, Helpers* Helper, double& vehicleMass, double& vehicleLoading, double& vehicleMassRot, double& crossArea, double& cWValue, double& f0, double& f1, double& f2, double& f3, double& f4, double& axleRatio, double& auxPower, double& ratedPower, double& engineIdlingSpeed, double& engineRatedSpeed, double& effectiveWheelDiameter, std::vector& transmissionGearRatios, std::string& vehicleMassType, std::string& vehicleFuelType, double& pNormV0, double& pNormP0, double& pNormV1, double& pNormP1, std::vector >& matrixSpeedInertiaTable, std::vector >& normedDragTable); ++ bool ReadVehicleFile(const std::vector& DataPath, const std::string& emissionClass, Helpers* Helper, double& vehicleMass, double& vehicleLoading, double& vehicleMassRot, double& crossArea, double& cWValue, double& f0, double& f1, double& f2, double& f3, double& f4, double& axleRatio, double& auxPower, double& ratedPower, double& engineIdlingSpeed, double& engineRatedSpeed, double& effectiveWheelDiameter, std::vector& transmissionGearRatios, std::string& vehicleMassType, std::string& vehicleFuelType, double& pNormV0, double& pNormP0, double& pNormV1, double& pNormP1, std::vector >& matrixSpeedInertiaTable, std::vector >& normedDragTable); + +- bool ReadEmissionData(bool readFC, const std::string& DataPath, const std::string& emissionClass, Helpers* Helper, std::vector& header, std::vector >& matrix, std::vector& idlingValues); ++ bool ReadEmissionData(bool readFC, const std::vector& DataPath, const std::string& emissionClass, Helpers* Helper, std::vector& header, std::vector >& matrix, std::vector& idlingValues); + + + //-------------------------------------------------------------------------------------------------- +@@ -61,10 +81,10 @@ namespace PHEMlightdll { + double todouble(const std::string& s); + + //Convert string to double list +- std::vector todoubleList(std::vector& s); ++ std::vector todoubleList(const std::vector& s); + + //Read a line from file +- std::string ReadLine(StreamReader* s); ++ std::string ReadLine(std::ifstream& s); + }; + } + +diff --git b/src/foreign/PHEMlight/cpp/Constants.cpp a/src/foreign/PHEMlight/cpp/Constants.cpp +index e534017678..936416fe08 100644 +--- b/src/foreign/PHEMlight/cpp/Constants.cpp ++++ a/src/foreign/PHEMlight/cpp/Constants.cpp +@@ -1,4 +1,25 @@ +-#include "Constants.h" ++/****************************************************************************/ ++// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo ++// Copyright (C) 2016-2018 German Aerospace Center (DLR) and others. ++// PHEMlight module ++// Copyright (C) 2016-2017 Technische Universitaet Graz, https://www.tugraz.at/ ++// This program and the accompanying materials ++// are made available under the terms of the Eclipse Public License v2.0 ++// which accompanies this distribution, and is available at ++// http://www.eclipse.org/legal/epl-v20.html ++// SPDX-License-Identifier: EPL-2.0 ++/****************************************************************************/ ++/// @file Constants.cpp ++/// @author Martin Dippold ++/// @author Michael Behrisch ++/// @date July 2016 ++/// @version $Id$ ++/// ++// ++/****************************************************************************/ ++ ++ ++#include "Constants.h" + + + namespace PHEMlightdll { +diff --git b/src/foreign/PHEMlight/cpp/Constants.h a/src/foreign/PHEMlight/cpp/Constants.h +index bd3387c15b..113c4247c7 100644 +--- b/src/foreign/PHEMlight/cpp/Constants.h ++++ a/src/foreign/PHEMlight/cpp/Constants.h +@@ -1,4 +1,25 @@ +-#ifndef PHEMlightCONSTANTS ++/****************************************************************************/ ++// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo ++// Copyright (C) 2016-2018 German Aerospace Center (DLR) and others. ++// PHEMlight module ++// Copyright (C) 2016-2017 Technische Universitaet Graz, https://www.tugraz.at/ ++// This program and the accompanying materials ++// are made available under the terms of the Eclipse Public License v2.0 ++// which accompanies this distribution, and is available at ++// http://www.eclipse.org/legal/epl-v20.html ++// SPDX-License-Identifier: EPL-2.0 ++/****************************************************************************/ ++/// @file Constants.h ++/// @author Martin Dippold ++/// @author Michael Behrisch ++/// @date July 2016 ++/// @version $Id$ ++/// ++// ++/****************************************************************************/ ++ ++ ++#ifndef PHEMlightCONSTANTS + #define PHEMlightCONSTANTS + + #include +diff --git b/src/foreign/PHEMlight/cpp/Helpers.cpp a/src/foreign/PHEMlight/cpp/Helpers.cpp +index b3872222ff..c3e6912ce8 100644 +--- b/src/foreign/PHEMlight/cpp/Helpers.cpp ++++ a/src/foreign/PHEMlight/cpp/Helpers.cpp +@@ -1,4 +1,25 @@ +-#include "Helpers.h" ++/****************************************************************************/ ++// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo ++// Copyright (C) 2016-2018 German Aerospace Center (DLR) and others. ++// PHEMlight module ++// Copyright 2016 Technische Universitaet Graz, https://www.tugraz.at/ ++// This program and the accompanying materials ++// are made available under the terms of the Eclipse Public License v2.0 ++// which accompanies this distribution, and is available at ++// http://www.eclipse.org/legal/epl-v20.html ++// SPDX-License-Identifier: EPL-2.0 ++/****************************************************************************/ ++/// @file Helpers.cpp ++/// @author Martin Dippold ++/// @author Michael Behrisch ++/// @date July 2016 ++/// @version $Id$ ++/// ++// ++/****************************************************************************/ ++ ++ ++#include "Helpers.h" + #include "Constants.h" + + +diff --git b/src/foreign/PHEMlight/cpp/Helpers.h a/src/foreign/PHEMlight/cpp/Helpers.h +index 0f6ad8eefb..23b41471a2 100644 +--- b/src/foreign/PHEMlight/cpp/Helpers.h ++++ a/src/foreign/PHEMlight/cpp/Helpers.h +@@ -1,4 +1,25 @@ +-#ifndef PHEMlightHELPERS ++/****************************************************************************/ ++// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo ++// Copyright (C) 2016-2018 German Aerospace Center (DLR) and others. ++// PHEMlight module ++// Copyright 2016 Technische Universitaet Graz, https://www.tugraz.at/ ++// This program and the accompanying materials ++// are made available under the terms of the Eclipse Public License v2.0 ++// which accompanies this distribution, and is available at ++// http://www.eclipse.org/legal/epl-v20.html ++// SPDX-License-Identifier: EPL-2.0 ++/****************************************************************************/ ++/// @file Helpers.h ++/// @author Martin Dippold ++/// @author Michael Behrisch ++/// @date July 2016 ++/// @version $Id$ ++/// ++// ++/****************************************************************************/ ++ ++ ++#ifndef PHEMlightHELPERS + #define PHEMlightHELPERS + + #include diff --git a/src/PHEMlightHandler.cpp b/src/PHEMlightHandler.cpp new file mode 100644 index 0000000..a4ab622 --- /dev/null +++ b/src/PHEMlightHandler.cpp @@ -0,0 +1,682 @@ +/********************************************************************************/ +// Vissim PHEMlight Handler +// Copyright (C) 2021 Karlsruhe Institut of Technology (KIT), https://ifv.kit.edu +// PHEMlight module +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0/ +// SPDX-License-Identifier: EPL-2.0 +/********************************************************************************/ +/// @file PHEMlightHandler.cpp +/// @author Sebastian Buck +/// @author Oliver Neumann +/// @date 2021/02/14 +/// +// +/****************************************************************************/ + +#include "PHEMlightHandler.h" + +#define DEBUG_PHEM_LIGHT 0 + +#if DEBUG_PHEM_LIGHT > 0 + +std::ofstream debug_phem_light("phemlight.txt"); + +#endif + +#define PROFILE_PHEM_LIGHT 0 + +#if PROFILE_PHEM_LIGHT > 0 + +#include +#include + +#include +using default_time = std::chrono::nanoseconds; + +std::ofstream profile_phem("profile_phem.txt"); + +#endif + +phem_light_handler::phem_light_handler() +{ + // Initalise cache for faster access + cached_emission = NULL; + cached_emission_id = -1; + cached_vehicle = NULL; + cached_vehicle_id = -1; + + // Initialise PHEMlight helper and cep class and + helper_init = false; +} + +phem_light_handler::~phem_light_handler() +{ + cached_emission = NULL; + cached_emission_id = -1; + cached_vehicle = NULL; + cached_vehicle_id = -1; + + for (std::map::iterator iterator_vehicles = vehicles.begin(); iterator_vehicles != vehicles.end(); iterator_vehicles++) + { + delete iterator_vehicles->second; + } + + for (std::map::iterator iterator_emissions = emissions.begin(); iterator_emissions != emissions.end(); iterator_emissions++) + { + delete iterator_emissions->second; + } + + for (std::map::iterator iterator_helpers = helpers.begin(); iterator_helpers != helpers.end(); iterator_helpers++) + { + delete iterator_helpers->second; + } + + for (std::map::iterator iterator_cep_handlers = cep_handlers.begin(); iterator_cep_handlers != cep_handlers.end(); iterator_cep_handlers++) + { + delete iterator_cep_handlers->second; + } +} + +bool phem_light_handler::read_config() +{ + // define config file input stream + ifstream config("Vissim_PHEMlight.cfg"); + string line; + string base_path = ""; + if (config.is_open()) + { + // if file could be opened + while (getline(config, line)) + { + // read line + if (line.length() > 0 && line[0] != '#') + { + // skip lines with "#" at the beginning + if (line.find("PATH") != string::npos) + { + // line contains "PATH" so base path should be defined + base_path = line.substr(line.find("=") + 1); + + // skip empty spaces + base_path.erase(0, base_path.find_first_not_of(' ')); + base_path.erase(base_path.find_last_not_of(' ') + 1); + + if (base_path.back() != '\\') + { + // check whether the path ends with "\" if not, append "\" to string + base_path += "\\"; + } + } + else + { + // parse config line + vector cells; + istringstream linestream(line); + string s; + while (getline(linestream, s, ';')) + { + // split line by ";" + cells.push_back(s); + } + + long vissim_id = -1; + if (cells[0].compare("DEFAULT") != 0) + { + // if vehicle id is not default set id + vissim_id = stoi(cells[0]); + } + string vehicle_type = cells[1]; + string power_type = cells[2]; + string eu_class = cells[3]; + + // fleet currently not supported + // helper.setclass nor working + PHEMlightdll::Helpers *helper = new PHEMlightdll::Helpers(); + PHEMlightdll::CEPHandler *cep_handler = new PHEMlightdll::CEPHandler(); + + bool valid = false; + if (eu_class.substr(0, 2).compare("EU") == 0) + { + // if eu class starts with "EU" helper class must be initialized with _eu_class + valid = helper->setclass(vehicle_type + "_" + power_type + "_" + eu_class); + } + else + { + // otherwise without _eu_class + valid = helper->setclass(vehicle_type + "_" + power_type); + } + + if (!valid) + { +// return false if parsing failed +#if DEBUG_PHEM_LIGHT >= 1 + debug_phem_light << " " << helper->getErrMsg() << std::endl; +#endif + return false; + } + // otherwise set helper class + helper->setvClass(vehicle_type); + helper->settClass(power_type); + helper->seteClass(eu_class); + helper->setCommentPrefix("c"); + + std::vector vec = std::vector(); + vec.push_back(base_path); + if (!cep_handler->GetCEP(vec, helper)) + { +// return false if get cep failed +#if DEBUG_PHEM_LIGHT >= 1 + debug_phem_light << " While getting cep." << std::endl; + debug_phem_light << base_path << std::endl; +#endif + return false; + } + if (vissim_id == -1) + { + // if vehicle id is -1 the default helper and cep_handler will be set + default_helper = helper; + default_cep_handler = cep_handler; + } + else + { + // otherwise helper and cep_handler will be added to PHEMlightHandler + create_phemlight_helper(vissim_id, helper); + create_phemlight_cep_handlers(vissim_id, cep_handler); + } + } + } + } + config.close(); + } + else + { +// error while trying to read config file +#if DEBUG_PHEM_LIGHT >= 1 + debug_phem_light << " Unable to find or open config.txt in project directory." << std::endl; +#endif + return false; + } + return true; +} + +bool phem_light_handler::create_phemlight_helper(long id, PHEMlightdll::Helpers *helper) +{ +#if PROFILE_PHEM_LIGHT > 0 + auto start = std::chrono::high_resolution_clock::now(); +#endif + + // assume phemlight helper id not existing + if (helpers.find(id) == helpers.end()) + { + // no matching id found -> can insert helper + // insert helper to map + helpers.insert(std::pair(id, helper)); + +#if PROFILE_PHEM_LIGHT > 0 + auto end = std::chrono::high_resolution_clock::now(); + profile_phem << "PHEM_CREATE_HELPER;" << std::chrono::duration_cast(end - start).count() << std::endl; +#endif + + return true; + } + else + { +// found existing helper for id -> can't insert helper +#if DEBUG_PHEM_LIGHT >= 1 + debug_phem_light << " Vehicle with id " << id << " already exists in create_vehicle." << std::endl; +#endif + return false; + } +} + +PHEMlightdll::Helpers *phem_light_handler::get_phemlight_helper(long id) +{ +#if PROFILE_PHEM_LIGHT > 0 + auto start = std::chrono::high_resolution_clock::now(); +#endif + + // assume id is in helper + std::map::iterator element = helpers.find(id); + PHEMlightdll::Helpers *helper; + if (element == helpers.end()) + { + // no helper for given id found -> return default helper + helper = default_helper; + } + else + { + helper = element->second; + } + +#if PROFILE_PHEM_LIGHT > 0 + auto end = std::chrono::high_resolution_clock::now(); + profile_phem << "PHEM_GET_HELPER;" << std::chrono::duration_cast(end - start).count() << std::endl; +#endif + + // return helper + return helper; +} + +bool phem_light_handler::create_phemlight_cep_handlers(long id, PHEMlightdll::CEPHandler *cep_handler) +{ +#if PROFILE_PHEM_LIGHT > 0 + auto start = std::chrono::high_resolution_clock::now(); +#endif + + // assume phemlight handler id not existing + if (cep_handlers.find(id) == cep_handlers.end()) + { + // no matching id found -> can insert handler + // insert handler to map + cep_handlers.insert(std::pair(id, cep_handler)); + +#if PROFILE_PHEM_LIGHT > 0 + auto end = std::chrono::high_resolution_clock::now(); + profile_phem << "PHEM_CREATE_CEP_HANDLER;" << std::chrono::duration_cast(end - start).count() << std::endl; +#endif + + return true; + } + else + { +// found existing handler for id -> can't insert handler +#if DEBUG_PHEM_LIGHT >= 1 + debug_phem_light << " Vehicle with id " << id << " already exists in create_vehicle." << std::endl; +#endif + return false; + } +} + +PHEMlightdll::CEPHandler *phem_light_handler::get_phemlight_cep_handlers(long id) +{ +#if PROFILE_PHEM_LIGHT > 0 + auto start = std::chrono::high_resolution_clock::now(); +#endif + + // assume id is in handler + std::map::iterator element = cep_handlers.find(id); + PHEMlightdll::CEPHandler *cep_handler; + if (element == cep_handlers.end()) + { + // no handler for given id found -> return default cep_handler + cep_handler = default_cep_handler; + } + else + { + cep_handler = element->second; + } + +#if PROFILE_PHEM_LIGHT > 0 + auto end = std::chrono::high_resolution_clock::now(); + profile_phem << "PHEM_GET_CEP_HANDLER;" << std::chrono::duration_cast(end - start).count() << std::endl; +#endif + + // return handler + return cep_handler; +} + +bool phem_light_handler::create_vehicle(long id, long type) +{ +#if PROFILE_PHEM_LIGHT > 0 + auto start = std::chrono::high_resolution_clock::now(); +#endif + + // assume vehicle id not existing + if (vehicles.find(id) == vehicles.end()) + { + // no matching id found -> can insert vehicle + vehicle *new_vehicle = new vehicle(type); + + // set cache + cached_vehicle = new_vehicle; + cached_vehicle_id = id; + + // insert vehicle to map + vehicles.insert(std::pair(id, new_vehicle)); + +#if PROFILE_PHEM_LIGHT > 0 + auto end = std::chrono::high_resolution_clock::now(); + profile_phem << "PHEM_CREATE_VEHICLE;" << std::chrono::duration_cast(end - start).count() << std::endl; +#endif + + return true; + } + else + { +// found existing vehicle id -> can't insert vehicle +#if DEBUG_PHEM_LIGHT >= 1 + debug_phem_light << " Vehicle with id " << id << " already exists in create_vehicle." << std::endl; +#endif + return false; + } +} + +bool phem_light_handler::destroy_vehicle(long id) +{ +#if PROFILE_PHEM_LIGHT > 0 + auto start = std::chrono::high_resolution_clock::now(); +#endif + + // assume vehicle id existing + // clear cache + if (cached_emission_id == id) + { + cached_emission_id = -1; + cached_emission = NULL; + } + if (cached_vehicle_id == id) + { + cached_vehicle_id = -1; + cached_vehicle = NULL; + } + + // check for delete vehicle + std::map::iterator vehicles_element = vehicles.find(id); + if (vehicles_element == vehicles.end()) + { +// no matching id found -> can't remove vehicle from map +#if DEBUG_PHEM_LIGHT >= 1 + debug_phem_light << " No vehicle for id " << id << " found in destroy_vehicle." << std::endl; +#endif + return false; + } + + // check for delete emission + std::map::iterator emission_element = emissions.find(id); + if (emission_element == emissions.end()) + { +// no matching id found -> can't remove vehicle from map +#if DEBUG_PHEM_LIGHT >= 1 + debug_phem_light << " No emission for id " << id << " found in destroy_vehicle." << std::endl; +#endif + return false; + } + + // found existing vehicle id -> can remove vehicle from map + delete vehicles_element->second; + vehicles.erase(id); + + // found existing vehicle id -> can remove vehicle from map + delete emission_element->second; + emissions.erase(id); + +#if PROFILE_PHEM_LIGHT > 0 + auto end = std::chrono::high_resolution_clock::now(); + profile_phem << "PHEM_DESTROY_VEHICLE;" << std::chrono::duration_cast(end - start).count() << std::endl; +#endif + + return true; +} + +vehicle *phem_light_handler::get_vehicle(long id) +{ +#if PROFILE_PHEM_LIGHT > 0 + auto start = std::chrono::high_resolution_clock::now(); +#endif + + // assume id is in vehicles + // check cached vehicle first + vehicle *veh; + if (cached_vehicle_id == id) + { + veh = cached_vehicle; + } + else + { + std::map::iterator element = vehicles.find(id); + if (element == vehicles.end()) + { +// no emission for given id found +#if DEBUG_PHEM_LIGHT >= 2 + debug_phem_light << " No vehicle for id " << id << " found in get_vehicle." << std::endl; +#endif + return NULL; + } + else + { + // vehicle for given id exists + // update cache + cached_vehicle_id = id; + cached_vehicle = element->second; + + veh = element->second; + } + } + +#if PROFILE_PHEM_LIGHT > 0 + auto end = std::chrono::high_resolution_clock::now(); + profile_phem << "PHEM_GET_VEHICLE;" << std::chrono::duration_cast(end - start).count() << std::endl; +#endif + + // return vehicle + return veh; +} + +emission *phem_light_handler::calculate_vehicle_emission(vehicle *veh) +{ +#if PROFILE_PHEM_LIGHT > 0 + auto start = std::chrono::high_resolution_clock::now(); +#endif + + PHEMlightdll::Helpers *helper = get_phemlight_helper(veh->type); + PHEMlightdll::CEPHandler *cep_handler = get_phemlight_cep_handlers(veh->type); + if (cep_handler->getCEPS().find(helper->getgClass()) != cep_handler->getCEPS().end()) + { + // CEPS found + PHEMlightdll::CEP *cep = cep_handler->getCEPS().find(helper->getgClass())->second; + + /*** + * Actually from PHEMlight cs code in starter. + * Fleet currently not working because missing code in sumo cpp. + ***/ + double time = veh->timestep; + double gradient = veh->slope; + + // set speed and acceleration with limitations + double velocity = 0; + if (veh->velocity > 0) + { + velocity = veh->velocity; + } + double acceleration = veh->acceleration; + if (velocity == 0) + { + acceleration = 0; + } + else if (acceleration > cep->GetMaxAccel(velocity, gradient)) + { + acceleration = cep->GetMaxAccel(velocity, gradient); + } + + // calculate the power + double power = cep->CalcPower(velocity, acceleration, gradient); + double energie = cep->CalcEngPower(power); + + emission *emis = new emission(0.0); + // calculate result if BEV + if (helper->gettClass() == PHEMlightdll::Constants::strBEV) + { + emis->fuel_consumption = cep->GetEmission("FC", power, velocity, helper) / 3600.0; + emis->norm_drive = energie / cep->getDrivingPower(); + emis->norm_rated = energie / cep->getRatedPower(); + emis->co = 0; + emis->co2 = 0; + emis->hc = 0; + emis->nox = 0; + emis->pm = 0; + } + else + { + double decel_coast = cep->GetDecelCoast(velocity, acceleration, gradient); + + // calculate the result values (zero emissions by costing, idling emissions by v <= 0.5m/s�) + if (acceleration >= decel_coast || velocity <= PHEMlightdll::Constants::ZERO_SPEED_ACCURACY) + { + double fuel_consumption = cep->GetEmission("FC", power, velocity, helper); + emis->norm_drive = energie / cep->getDrivingPower(); + emis->norm_rated = energie / cep->getRatedPower(); + double co = cep->GetEmission("CO", power, velocity, helper); + double hc = cep->GetEmission("HC", power, velocity, helper); + double nox = cep->GetEmission("NOx", power, velocity, helper); + double pm = cep->GetEmission("PM", power, velocity, helper); + emis->co2 = cep->GetCO2Emission(fuel_consumption, co, hc, helper) / 3600.0; + emis->fuel_consumption = fuel_consumption / 3600.0; + emis->co = co / 3600.0; + emis->hc = hc / 3600.0; + emis->nox = nox / 3600.0; + emis->pm = pm / 3600.0; + } + else + { + emis->fuel_consumption = 0; + emis->norm_drive = energie / cep->getDrivingPower(); + emis->norm_rated = energie / cep->getRatedPower(); + emis->co = 0; + emis->co2 = 0; + emis->hc = 0; + emis->nox = 0; + emis->pm = 0; + } + } + +#if DEBUG_PHEM_LIGHT >= 2 + debug_phem_light << " Calculation Done. Calculated FC " << emis->fuel_consumption << " ND " << emis->norm_drive << " NDR " << emis->norm_rated + << " CO " << emis->co << " CO2 " << emis->co2 << " HC " << emis->hc << " NOx " << emis->nox << " PM " << emis->pm << std::endl; +#endif + +#if PROFILE_PHEM_LIGHT > 0 + auto end = std::chrono::high_resolution_clock::now(); + profile_phem << "PHEM_CALC_EMISSION;" << std::chrono::duration_cast(end - start).count() << std::endl; +#endif + + return emis; + } + else + { +// no entry in CEPS found +#if DEBUG_PHEM_LIGHT >= 1 + debug_phem_light << " No CEPS found." << std::endl; +#endif + return NULL; + } +} + +bool phem_light_handler::calculate_vehicle_emission(long id) +{ +#if PROFILE_PHEM_LIGHT > 0 + auto start = std::chrono::high_resolution_clock::now(); +#endif + + if (helper_init == false) + { + read_config(); + helper_init = true; + } + // free emission object if necessary and set new one + // check cached vehicle first + vehicle *veh = NULL; + if (cached_vehicle_id == id) + { + veh = cached_vehicle; + } + else + { + std::map::iterator element = vehicles.find(id); + if (element == vehicles.end()) + { +// no vehicle for given id found +#if DEBUG_PHEM_LIGHT >= 1 + debug_phem_light << " No vehicle for id " << id << " found in calculate_vehicle_emission." << std::endl; +#endif + return false; + } + else + { + veh = element->second; + cached_vehicle_id = id; + cached_vehicle = veh; + } + } + + // calculate emission + emission *emis = calculate_vehicle_emission(veh); + + if (emis == NULL) + { + return false; + } + + // update cache + cached_emission = emis; + cached_emission_id = id; + + // insert or replace emission + if (emissions.find(id) == emissions.end()) + { + // no emission for given id found -> only insert emission for id + emissions.insert(std::pair(id, emis)); + } + else + { + // emission for given id exists -> free old emission and set new one + delete emissions.find(id)->second; + emissions.erase(id); + emissions.insert(std::pair(id, emis)); + } + +#if PROFILE_PHEM_LIGHT > 0 + auto end = std::chrono::high_resolution_clock::now(); + profile_phem << "PHEM_CALC_EMISSION_PUB;" << std::chrono::duration_cast(end - start).count() << std::endl; +#endif + + return true; +} + +emission *phem_light_handler::get_vehicle_emission(long id) +{ +#if PROFILE_PHEM_LIGHT > 0 + auto start = std::chrono::high_resolution_clock::now(); +#endif + + // assume id is in emissions + // check cached emission first + emission *emis; + if (cached_emission_id == id) + { + emis = cached_emission; + } + else + { + std::map::iterator element = emissions.find(id); + if (element == emissions.end()) + { + // no emission for given id found +#if DEBUG_PHEM_LIGHT >= 1 + debug_phem_light << " Vehicle id for get request not found." << std::endl; +#endif + return NULL; + } + else + { +#if DEBUG_PHEM_LIGHT >= 3 + debug_phem_light << " Returning emission for vehicle " << id << "." << std::endl; +#endif + // emission for given id exists + // update cache + this->cached_emission_id = id; + this->cached_emission = element->second; + + emis = element->second; + } + } + +#if PROFILE_PHEM_LIGHT > 0 + auto end = std::chrono::high_resolution_clock::now(); + profile_phem << "PHEM_GET_VEHICLE_EMISSION;" << std::chrono::duration_cast(end - start).count() << std::endl; +#endif + + // return emission + return emis; +} diff --git a/src/PHEMlightHandler.h b/src/PHEMlightHandler.h new file mode 100644 index 0000000..0cc040e --- /dev/null +++ b/src/PHEMlightHandler.h @@ -0,0 +1,140 @@ +/********************************************************************************/ +// Vissim PHEMlight Handler +// Copyright (C) 2021 Karlsruhe Institut of Technology (KIT), https://ifv.kit.edu +// PHEMlight module +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0/ +// SPDX-License-Identifier: EPL-2.0 +/********************************************************************************/ +/// @file PHEMlightHandler.h +/// @author Sebastian Buck +/// @author Oliver Neumann +/// @date 2021/02/14 +/// +// +/****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "PHEMlight/CEP.h" +#include "PHEMlight/CEPHandler.h" +#include "PHEMlight/Constants.h" +#include "PHEMlight/Helpers.h" + +using namespace std; + +struct vehicle +{ + long type; + double acceleration; + double velocity; + double slope; + double weight; + double timestep; + + vehicle() : type(-1) {} + + vehicle(long p_type) : type(p_type) {} + + vehicle(long p_type, double p_acceleration, double p_velocity, double p_slope, double p_weight, double p_timestep) + { + type = p_type; + acceleration = p_acceleration; + velocity = p_velocity; + slope = p_slope; + weight = p_weight; + timestep = p_timestep; + } +}; + +struct emission +{ + double fuel_consumption; // [g/s] / [kWh/s for BEV] + double norm_drive; // + double norm_rated; // + double co; // [g/s] + double co2; // [g/s] + double hc; // [g/s] + double nox; // [g/s] + double pm; // [g/s] + + emission(double default_value) + { + fuel_consumption = default_value; + norm_drive = default_value; + norm_rated = default_value; + co = default_value; + co2 = default_value; + hc = default_value; + nox = default_value; + pm = default_value; + } + + emission() + { + fuel_consumption = 0.1; + norm_drive = 0.2; + norm_rated = 0.3; + co = 0.4; + co2 = 0.5; + hc = 0.6; + nox = 0.7; + pm = 0.8; + } + + emission(double p_fuel_consumption, double p_norm_drive, double p_norm_rated, double p_co, double p_co2, double p_hc, double p_nox, double p_pm) + { + fuel_consumption = p_fuel_consumption; + norm_drive = p_norm_drive; + norm_rated = p_norm_rated; + co = p_co; + co2 = p_co2; + hc = p_hc; + nox = p_nox; + pm = p_pm; + } +}; + +class phem_light_handler +{ + +private: + std::map vehicles; + std::map emissions; + + // emission and vehicle cache + emission *cached_emission; + long cached_emission_id; + vehicle *cached_vehicle; + long cached_vehicle_id; + + bool helper_init; + PHEMlightdll::Helpers *default_helper; + PHEMlightdll::CEPHandler *default_cep_handler; + std::map helpers; + std::map cep_handlers; + + bool create_phemlight_helper(long id, PHEMlightdll::Helpers *helper); + PHEMlightdll::Helpers *get_phemlight_helper(long id); + bool create_phemlight_cep_handlers(long id, PHEMlightdll::CEPHandler *cep_handler); + PHEMlightdll::CEPHandler *get_phemlight_cep_handlers(long id); + + bool read_config(); + + emission *calculate_vehicle_emission(vehicle *veh); + +public: + phem_light_handler(); + ~phem_light_handler(); + + bool create_vehicle(long id, long type); + bool destroy_vehicle(long id); + vehicle *get_vehicle(long id); + bool calculate_vehicle_emission(long id); + emission *get_vehicle_emission(long id); +}; diff --git a/src/Vissim_PHEMlight.vcxproj b/src/Vissim_PHEMlight.vcxproj new file mode 100644 index 0000000..df918c3 --- /dev/null +++ b/src/Vissim_PHEMlight.vcxproj @@ -0,0 +1,275 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {E7760DFC-DC4C-4A0B-AF80-5DA2AFE88542} + SAK + SAK + SAK + SAK + 10.0 + + + + DynamicLibrary + v142 + false + MultiByte + + + DynamicLibrary + v142 + false + MultiByte + + + DynamicLibrary + v142 + false + MultiByte + + + DynamicLibrary + v142 + false + MultiByte + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>15.0.27625.0 + + + $(SolutionDir)Bin\$(Configuration)\ + $(SolutionDir)Temp\$(Configuration)\$(ProjectName)\ + true + + + true + + + $(SolutionDir)Bin\$(Configuration)\ + $(SolutionDir)Temp\$(Configuration)\$(ProjectName)\ + false + + + false + + + + /D_WIN32_WINNT=0x0400 /D _WIN32_IE=0x0400 %(AdditionalOptions) + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;EMISSIONMODEL_EXPORTS;%(PreprocessorDefinitions) + Default + MultiThreadedDebugDLL + + $(SolutionDir)Temp\$(Configuration)\$(ProjectName)\$(ProjectName).pch + $(SolutionDir)Temp\$(Configuration)\$(ProjectName)\$(ProjectName) + $(SolutionDir)Temp\$(Configuration)\$(ProjectName)/ + $(SolutionDir)Temp\$(Configuration)\$(ProjectName)\$(ProjectName) + Level3 + true + EditAndContinue + + + $(OutDir)$(ProjectName).dll + true + $(SolutionDir)Lib\$(Configuration)\;%(AdditionalLibraryDirectories) + true + $(SolutionDir)Temp\$(Configuration)\$(ProjectName)\$(ProjectName).pdb + $(SolutionDir)Lib\$(Configuration)\$(ProjectName).lib + MachineX86 + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Debug/EmissionModel.tlb + + + + _DEBUG;%(PreprocessorDefinitions) + 0x0407 + + + + + /D_WIN32_WINNT=0x0400 /D _WIN32_IE=0x0400 %(AdditionalOptions) + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;EMISSIONMODEL_EXPORTS;%(PreprocessorDefinitions) + Default + MultiThreadedDebugDLL + + + $(SolutionDir)Temp\$(Configuration)\$(ProjectName)\$(ProjectName).pch + $(SolutionDir)Temp\$(Configuration)\$(ProjectName)\$(ProjectName) + $(SolutionDir)Temp\$(Configuration)\$(ProjectName)/ + $(SolutionDir)Temp\$(Configuration)\$(ProjectName)\$(ProjectName) + Level3 + true + ProgramDatabase + + + $(OutDir)$(ProjectName).dll + true + $(SolutionDir)Lib\$(Configuration)\;%(AdditionalLibraryDirectories) + true + $(SolutionDir)Temp\$(Configuration)\$(ProjectName)\$(ProjectName).pdb + $(SolutionDir)Lib\$(Configuration)\$(ProjectName).lib + + + _DEBUG;%(PreprocessorDefinitions) + true + true + .\Debug/EmissionModel.tlb + + + + + _DEBUG;%(PreprocessorDefinitions) + 0x0407 + + + + + /D_WIN32_WINNT=0x0400 /D _WIN32_IE=0x0400 %(AdditionalOptions) + MaxSpeed + OnlyExplicitInline + WIN32;NDEBUG;_WINDOWS;_USRDLL;EMISSIONMODEL_EXPORTS;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + true + + $(SolutionDir)Temp\$(Configuration)\$(ProjectName)\$(ProjectName).pch + $(SolutionDir)Temp\$(Configuration)\$(ProjectName)\$(ProjectName) + $(SolutionDir)Temp\$(Configuration)\$(ProjectName)/ + $(SolutionDir)Temp\$(Configuration)\$(ProjectName)\$(ProjectName) + Level3 + true + + + $(OutDir)$(ProjectName).dll + true + $(SolutionDir)Bin\$(Configuration)\;%(AdditionalLibraryDirectories) + + $(SolutionDir)Lib\$(Configuration)\$(ProjectName).lib + MachineX86 + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Release/EmissionModel.tlb + + + + NDEBUG;%(PreprocessorDefinitions) + 0x0407 + + + + + /D_WIN32_WINNT=0x0400 /D _WIN32_IE=0x0400 %(AdditionalOptions) + MaxSpeed + OnlyExplicitInline + WIN32;NDEBUG;_WINDOWS;_USRDLL;EMISSIONMODEL_EXPORTS;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + true + + + $(SolutionDir)Temp\$(Configuration)\$(ProjectName)\$(ProjectName).pch + $(SolutionDir)Temp\$(Configuration)\$(ProjectName)\$(ProjectName) + $(SolutionDir)Temp\$(Configuration)\$(ProjectName)/ + $(SolutionDir)Temp\$(Configuration)\$(ProjectName)\$(ProjectName) + Level3 + true + + + $(OutDir)$(ProjectName).dll + true + $(SolutionDir)Bin\$(Configuration)\;%(AdditionalLibraryDirectories) + + + $(SolutionDir)Lib\$(Configuration)\$(ProjectName).lib + + + NDEBUG;%(PreprocessorDefinitions) + true + true + .\Release/EmissionModel.tlb + + + + + NDEBUG;%(PreprocessorDefinitions) + 0x0407 + + + + + Disabled + Disabled + WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;EMISSIONMODEL_EXPORTS + WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;EMISSIONMODEL_EXPORTS + EnableFastChecks + EnableFastChecks + MaxSpeed + MaxSpeed + WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;EMISSIONMODEL_EXPORTS + WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;EMISSIONMODEL_EXPORTS + + + + + + + + + + + + + + + + + + +