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