From 7c4d91f9a730b0a7a46c49bacd7197df1a0252cf Mon Sep 17 00:00:00 2001
From: Markus Quaritsch <markus.quaritsch@tugraz.at>
Date: Mon, 3 Aug 2015 17:23:44 +0200
Subject: [PATCH] introduce combustion engine model for engine-only cycles
 (handling of overload situations) introduce minimum acceleration in driver
 model (abort otherwise) interpretation of driving cycle (stop-time + increase
 distance), altitude computation make all testcases green...

---
 VectoCore/Configuration/Constants.cs          |  2 +-
 .../FileIO/Reader/DrivingCycleDataReader.cs   | 18 +++-
 .../Simulation/Impl/PowertrainBuilder.cs      | 35 ++------
 .../Data/DrivingCycleData.cs                  | 20 +++++
 .../Impl/CombustionEngine.cs                  | 77 ++++++++---------
 .../Impl/DistanceBasedDrivingCycle.cs         |  1 -
 .../Models/SimulationComponent/Impl/Driver.cs |  4 +-
 .../Impl/EngineOnlyCombustionEngine.cs        | 84 +++++++++++++++++++
 .../SimulationComponent/Impl/Vehicle.cs       |  9 +-
 VectoCore/VectoCore.csproj                    |  1 +
 .../EngineOnlyCycle/EngineOnlyCycleTest.cs    |  6 +-
 .../SimulationRuns/MinimalPowertrain.cs       | 68 ---------------
 .../CombustionEngineTest.cs                   |  2 +-
 .../DistanceBasedDrivingCycleTest.cs          | 15 ++--
 14 files changed, 186 insertions(+), 156 deletions(-)
 create mode 100644 VectoCore/Models/SimulationComponent/Impl/EngineOnlyCombustionEngine.cs

diff --git a/VectoCore/Configuration/Constants.cs b/VectoCore/Configuration/Constants.cs
index bb6b936c92..2c4e309c58 100644
--- a/VectoCore/Configuration/Constants.cs
+++ b/VectoCore/Configuration/Constants.cs
@@ -54,7 +54,7 @@ namespace TUGraz.VectoCore.Configuration
 			/// threshold for changes in the road gradient. changes below this threshold will be considered to be equal for filtering out the driving cycle.
 			/// altitude computation is done before filtering! 
 			/// </summary>
-			public static readonly double DrivingCycleRoadGradientTolerance = 0;
+			public static readonly double DrivingCycleRoadGradientTolerance = 1E-12;
 
 			//VectoMath.InclinationToAngle(0.25 / 100.0).Value();
 
diff --git a/VectoCore/FileIO/Reader/DrivingCycleDataReader.cs b/VectoCore/FileIO/Reader/DrivingCycleDataReader.cs
index 09b7b7c403..f0daad3e8d 100644
--- a/VectoCore/FileIO/Reader/DrivingCycleDataReader.cs
+++ b/VectoCore/FileIO/Reader/DrivingCycleDataReader.cs
@@ -69,16 +69,28 @@ namespace TUGraz.VectoCore.FileIO.Reader
 			filtered.Add(current);
 			var distance = current.Distance;
 			var altitude = current.Altitude;
-			foreach (var entry in entries) {
+			//foreach (var entry in entries) {
+			for (var i = 0; i < entries.Count; i++) {
+				var entry = entries[i];
+				if (i > 0) {
+					altitude += (entry.Distance - distance) * entries[i - 1].RoadGradientPercent / 100.0;
+				}
 				entry.Altitude = altitude;
 				if (!CycleEntriesAreEqual(current, entry)) {
 					entry.Altitude = altitude;
 					filtered.Add(entry);
 					current = entry;
 				}
-				if (entry.StoppingTime.IsEqual(0) && !entry.VehicleTargetSpeed.IsEqual(0)) {
-					altitude += (entry.Distance - distance) * entry.RoadGradientPercent / 100.0;
+				if (!entry.StoppingTime.IsEqual(0) && entry.VehicleTargetSpeed.IsEqual(0)) {
+					// vehicle stops. duplicate current distance entry with 0 waiting time
+					var tmp = new DrivingCycleData.DrivingCycleEntry(entry) {
+						StoppingTime = 0.SI<Second>(),
+						VehicleTargetSpeed = i < entries.Count - 1 ? entries[i + 1].VehicleTargetSpeed : 0.SI<MeterPerSecond>()
+					};
+					filtered.Add(tmp);
+					current = tmp;
 				}
+
 				distance = entry.Distance;
 			}
 			log.Info(string.Format("Data loaded. Number of Entries: {0}, filtered Entries: {1}", entries.Count, filtered.Count));
diff --git a/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs b/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs
index 77f1112e88..2106604cd5 100644
--- a/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs
+++ b/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs
@@ -91,9 +91,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl
 			return _container;
 		}
 
-		protected
-			IGearbox GetGearbox
-			(VehicleContainer container, GearboxData data)
+		protected IGearbox GetGearbox(VehicleContainer container, GearboxData data)
 		{
 			switch (data.Type) {
 				case GearboxData.GearboxType.AT:
@@ -105,59 +103,44 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl
 			}
 		}
 
-		protected virtual
-			IDriver AddComponent
-			(IDrivingCycle prev, IDriver next)
+		protected virtual IDriver AddComponent(IDrivingCycle prev, IDriver next)
 		{
 			prev.InPort().Connect(next.OutPort());
 			return next;
 		}
 
-		protected virtual
-			IVehicle AddComponent
-			(IDriver prev, IVehicle next)
+		protected virtual IVehicle AddComponent(IDriver prev, IVehicle next)
 		{
 			prev.InPort().Connect(next.OutPort());
 			return next;
 		}
 
-		protected virtual
-			IWheels AddComponent
-			(IFvInProvider prev, IWheels next)
+		protected virtual IWheels AddComponent(IFvInProvider prev, IWheels next)
 		{
 			prev.InPort().Connect(next.OutPort());
 			return next;
 		}
 
 
-		protected virtual
-			IPowerTrainComponent AddComponent
-			(IWheels prev, IPowerTrainComponent next)
+		protected virtual IPowerTrainComponent AddComponent(IWheels prev, IPowerTrainComponent next)
 		{
 			prev.InPort().Connect(next.OutPort());
 			return next;
 		}
 
-		protected virtual
-			IPowerTrainComponent AddComponent
-			(IPowerTrainComponent prev, IPowerTrainComponent next)
+		protected virtual IPowerTrainComponent AddComponent(IPowerTrainComponent prev, IPowerTrainComponent next)
 		{
 			prev.InPort().Connect(next.OutPort());
 			return next;
 		}
 
-		protected virtual
-			void AddComponent
-			(IPowerTrainComponent prev, ITnOutProvider next)
+		protected virtual void AddComponent(IPowerTrainComponent prev, ITnOutProvider next)
 		{
 			prev.InPort().Connect(next.OutPort());
 		}
 
 
-		private
-			VehicleContainer BuildEngineOnly
-			(VectoRunData
-				data)
+		private VehicleContainer BuildEngineOnly(VectoRunData data)
 		{
 			var cycle = new EngineOnlySimulation(_container, data.Cycle);
 
@@ -169,7 +152,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl
 			directAux.AddDirect(cycle);
 			gearbox.InPort().Connect(directAux.OutPort());
 
-			var engine = new CombustionEngine(_container, data.EngineData);
+			var engine = new EngineOnlyCombustionEngine(_container, data.EngineData);
 			directAux.InPort().Connect(engine.OutPort());
 
 			return _container;
diff --git a/VectoCore/Models/SimulationComponent/Data/DrivingCycleData.cs b/VectoCore/Models/SimulationComponent/Data/DrivingCycleData.cs
index eea002c181..6fdee417cd 100644
--- a/VectoCore/Models/SimulationComponent/Data/DrivingCycleData.cs
+++ b/VectoCore/Models/SimulationComponent/Data/DrivingCycleData.cs
@@ -22,6 +22,26 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
 
 		public class DrivingCycleEntry
 		{
+			public DrivingCycleEntry() {}
+
+			public DrivingCycleEntry(DrivingCycleEntry entry)
+			{
+				Distance = entry.Distance;
+				Time = entry.Time;
+				VehicleTargetSpeed = entry.VehicleTargetSpeed;
+				RoadGradient = entry.RoadGradient;
+				Altitude = entry.Altitude;
+				StoppingTime = entry.StoppingTime;
+				EngineSpeed = entry.EngineSpeed;
+				Gear = entry.Gear;
+				AdditionalAuxPowerDemand = entry.AdditionalAuxPowerDemand;
+				AirSpeedRelativeToVehicle = entry.AirSpeedRelativeToVehicle;
+				WindYawAngle = entry.WindYawAngle;
+				EngineTorque = entry.EngineTorque;
+				Drag = entry.Drag;
+				AuxiliarySupplyPower = new Dictionary<string, Watt>(entry.AuxiliarySupplyPower);
+			}
+
 			/// <summary>
 			///     [m]	Travelled distance used for distance-based cycles. If "t"
 			///     is also defined this column will be ignored.
diff --git a/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs b/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs
index 15b7c3a4dc..0bedf3609b 100644
--- a/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs
+++ b/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs
@@ -29,11 +29,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			Undef
 		}
 
-		private const int EngineIdleSpeedStopThreshold = 100;
-		private const double MaxPowerExceededThreshold = 1.05;
-		private const double ZeroThreshold = 0.0001;
-		private const double FullLoadMargin = 0.01;
-		[NonSerialized] private readonly List<Second> _enginePowerCorrections = new List<Second>();
+		protected const int EngineIdleSpeedStopThreshold = 100;
+		protected const double MaxPowerExceededThreshold = 1.05;
+		protected const double ZeroThreshold = 0.0001;
+		protected const double FullLoadMargin = 0.01;
 
 		/// <summary>
 		///     Current state is computed in request method
@@ -76,21 +75,15 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 
 		IResponse ITnOutPort.Request(Second absTime, Second dt, NewtonMeter torque, PerSecond engineSpeed, bool dryRun)
 		{
-			_currentState.dt = dt;
-			_currentState.EngineSpeed = engineSpeed;
-			_currentState.AbsTime = absTime;
-
-			var requestedPower = Formulas.TorqueToPower(torque, engineSpeed);
-			_currentState.EnginePowerLoss = InertiaPowerLoss(torque, engineSpeed);
-			var requestedEnginePower = requestedPower + _currentState.EnginePowerLoss;
-
-			if (engineSpeed < _data.IdleSpeed.Value() - EngineIdleSpeedStopThreshold) {
-				_currentState.OperationMode = EngineOperationMode.Stopped;
-				//todo: _currentState.EnginePowerLoss = enginePowerLoss;
-			}
+			return DoHandleRequest(absTime, dt, torque, engineSpeed, dryRun);
+		}
 
-			_currentState.FullDragTorque = _data.FullLoadCurve.DragLoadStationaryTorque(engineSpeed);
-			_currentState.FullDragPower = Formulas.TorqueToPower(_currentState.FullDragTorque, engineSpeed);
+		protected virtual IResponse DoHandleRequest(Second absTime, Second dt, NewtonMeter torque, PerSecond engineSpeed,
+			bool dryRun)
+		{
+			Watt requestedPower;
+			Watt requestedEnginePower;
+			ComputeRequestedEnginePower(absTime, dt, torque, engineSpeed, out requestedPower, out requestedEnginePower);
 
 			ComputeFullLoadPower(engineSpeed, dt);
 
@@ -118,6 +111,26 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			return new ResponseSuccess();
 		}
 
+		protected void ComputeRequestedEnginePower(Second absTime, Second dt, NewtonMeter torque, PerSecond engineSpeed,
+			out Watt requestedPower, out Watt requestedEnginePower)
+		{
+			_currentState.dt = dt;
+			_currentState.EngineSpeed = engineSpeed;
+			_currentState.AbsTime = absTime;
+
+			requestedPower = Formulas.TorqueToPower(torque, engineSpeed);
+			_currentState.EnginePowerLoss = InertiaPowerLoss(torque, engineSpeed);
+			requestedEnginePower = requestedPower + _currentState.EnginePowerLoss;
+
+			if (engineSpeed < _data.IdleSpeed.Value() - EngineIdleSpeedStopThreshold) {
+				_currentState.OperationMode = EngineOperationMode.Stopped;
+				//todo: _currentState.EnginePowerLoss = enginePowerLoss;
+			}
+
+			_currentState.FullDragTorque = _data.FullLoadCurve.DragLoadStationaryTorque(engineSpeed);
+			_currentState.FullDragPower = Formulas.TorqueToPower(_currentState.FullDragTorque, engineSpeed);
+		}
+
 		public IResponse Initialize(NewtonMeter torque, PerSecond engineSpeed)
 		{
 			_previousState = new EngineState() {
@@ -179,7 +192,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		///     Validates the requested power demand [W].
 		/// </summary>
 		/// <param name="requestedEnginePower">[W]</param>
-		protected void ValidatePowerDemand(SI requestedEnginePower)
+		protected virtual void ValidatePowerDemand(SI requestedEnginePower)
 		{
 			Contract.Requires(requestedEnginePower.HasEqualUnit(new SI().Watt));
 
@@ -198,25 +211,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		/// </summary>
 		/// <param name="requestedEnginePower">[W]</param>
 		/// <returns>[W]</returns>
-		protected Watt LimitEnginePower(Watt requestedEnginePower)
+		protected virtual Watt LimitEnginePower(Watt requestedEnginePower)
 		{
 			if (requestedEnginePower > _currentState.DynamicFullLoadPower) {
-				if (requestedEnginePower / _currentState.DynamicFullLoadPower > MaxPowerExceededThreshold) {
-					_enginePowerCorrections.Add(_currentState.AbsTime);
-					Log.WarnFormat(
-						"t: {0}  requested power > P_engine_full * 1.05 - corrected. P_request: {1}  P_engine_full: {2}",
-						_currentState.AbsTime, requestedEnginePower, _currentState.DynamicFullLoadPower);
-				}
 				return _currentState.DynamicFullLoadPower;
 			}
 			if (requestedEnginePower < _currentState.FullDragPower) {
-				if (requestedEnginePower / _currentState.FullDragPower > MaxPowerExceededThreshold &&
-					requestedEnginePower > -99999) {
-					_enginePowerCorrections.Add(_currentState.AbsTime);
-					Log.WarnFormat(
-						"t: {0}  requested power < P_engine_drag * 1.05 - corrected. P_request: {1}  P_engine_drag: {2}",
-						_currentState.AbsTime, requestedEnginePower, _currentState.FullDragPower);
-				}
 				return _currentState.FullDragPower;
 			}
 			return requestedEnginePower;
@@ -226,7 +226,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		///     Updates the engine state dependend on the requested power [W].
 		/// </summary>
 		/// <param name="requestedEnginePower">[W]</param>
-		protected void UpdateEngineState(Watt requestedEnginePower)
+		protected virtual void UpdateEngineState(Watt requestedEnginePower)
 		{
 			if (requestedEnginePower < -ZeroThreshold) {
 				_currentState.OperationMode = IsFullLoad(requestedEnginePower, _currentState.DynamicFullLoadPower)
@@ -242,13 +242,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			}
 		}
 
-		public IList<string> Warnings()
-		{
-			IList<string> retVal = new List<string>();
-			retVal.Add(string.Format("Engine power corrected (>5%) in {0} time steps ", _enginePowerCorrections.Count));
-			return retVal;
-		}
-
 		/// <summary>
 		///     computes full load power from gear [-], angularVelocity [rad/s] and dt [s].
 		/// </summary>
diff --git a/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs b/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs
index a252cd4421..2714f1ea59 100644
--- a/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs
+++ b/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs
@@ -33,7 +33,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		{
 			Data = cycle;
 			CycleIntervalIterator = new DrivingCycleEnumerator(Data);
-			CycleIntervalIterator.MoveNext();
 		}
 
 		#region IDrivingCycleInProvider
diff --git a/VectoCore/Models/SimulationComponent/Impl/Driver.cs b/VectoCore/Models/SimulationComponent/Impl/Driver.cs
index 2f6a8cc176..1d327b9f28 100644
--- a/VectoCore/Models/SimulationComponent/Impl/Driver.cs
+++ b/VectoCore/Models/SimulationComponent/Impl/Driver.cs
@@ -149,8 +149,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 					CurrentState.Acceleration += searchInterval;
 				}
 				// check for minimum acceleration, add some safety margin due to search
-				if (CurrentState.Acceleration < Constants.SimulationSettings.MinimumAcceleration / 5.0 &&
-					searchInterval < Constants.SimulationSettings.MinimumAcceleration.Value() / 20.0) {
+				if (Math.Abs(CurrentState.Acceleration.Value()) < Constants.SimulationSettings.MinimumAcceleration.Value() / 5.0 &&
+					Math.Abs(searchInterval) < Constants.SimulationSettings.MinimumAcceleration.Value() / 20.0) {
 					throw new VectoSimulationException("Could not achieve minimum acceleration");
 				}
 				searchInterval /= 2.0;
diff --git a/VectoCore/Models/SimulationComponent/Impl/EngineOnlyCombustionEngine.cs b/VectoCore/Models/SimulationComponent/Impl/EngineOnlyCombustionEngine.cs
new file mode 100644
index 0000000000..25c7f7fc3d
--- /dev/null
+++ b/VectoCore/Models/SimulationComponent/Impl/EngineOnlyCombustionEngine.cs
@@ -0,0 +1,84 @@
+using System.Collections.Generic;
+using TUGraz.VectoCore.Configuration;
+using TUGraz.VectoCore.Models.Connector.Ports;
+using TUGraz.VectoCore.Models.Connector.Ports.Impl;
+using TUGraz.VectoCore.Models.Simulation;
+using TUGraz.VectoCore.Models.SimulationComponent.Data;
+using TUGraz.VectoCore.Utils;
+
+namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
+{
+	public class EngineOnlyCombustionEngine : CombustionEngine
+	{
+		protected readonly List<Second> _enginePowerCorrections = new List<Second>();
+
+		public EngineOnlyCombustionEngine(IVehicleContainer cockpit, CombustionEngineData data) : base(cockpit, data) {}
+
+		// the behavior in engin-only mode differs a little bit from normal driving cycle simulation: in engine-only mode
+		// certain amount of overload is tolerated.
+		protected override IResponse DoHandleRequest(Second absTime, Second dt, NewtonMeter torque, PerSecond engineSpeed,
+			bool dryRun)
+		{
+			Watt requestedPower;
+			Watt requestedEnginePower;
+			ComputeRequestedEnginePower(absTime, dt, torque, engineSpeed, out requestedPower, out requestedEnginePower);
+
+			ComputeFullLoadPower(engineSpeed, dt);
+
+			ValidatePowerDemand(requestedEnginePower);
+
+			_currentState.EnginePower = LimitEnginePower(requestedEnginePower);
+
+			if (dryRun) {
+				return new ResponseDryRun() {
+					DeltaFullLoad = (requestedEnginePower - _currentState.DynamicFullLoadPower).Value(),
+					DeltaDragLoad = (requestedEnginePower - _currentState.FullDragPower).Value()
+				};
+			}
+
+			UpdateEngineState(_currentState.EnginePower);
+
+			// = requestedEnginePower; //todo + _currentState.EnginePowerLoss;
+			_currentState.EngineTorque = Formulas.PowerToTorque(_currentState.EnginePower,
+				_currentState.EngineSpeed);
+
+			return new ResponseSuccess();
+		}
+
+		/// <summary>
+		///     [W] => [W]
+		/// </summary>
+		/// <param name="requestedEnginePower">[W]</param>
+		/// <returns>[W]</returns>
+		protected override Watt LimitEnginePower(Watt requestedEnginePower)
+		{
+			if (requestedEnginePower > _currentState.DynamicFullLoadPower) {
+				if (requestedEnginePower / _currentState.DynamicFullLoadPower > MaxPowerExceededThreshold) {
+					_enginePowerCorrections.Add(_currentState.AbsTime);
+					Log.WarnFormat(
+						"t: {0}  requested power > P_engine_full * 1.05 - corrected. P_request: {1}  P_engine_full: {2}",
+						_currentState.AbsTime, requestedEnginePower, _currentState.DynamicFullLoadPower);
+				}
+				return _currentState.DynamicFullLoadPower;
+			}
+			if (requestedEnginePower < _currentState.FullDragPower) {
+				if (requestedEnginePower / _currentState.FullDragPower > MaxPowerExceededThreshold &&
+					requestedEnginePower > -99999) {
+					_enginePowerCorrections.Add(_currentState.AbsTime);
+					Log.WarnFormat(
+						"t: {0}  requested power < P_engine_drag * 1.05 - corrected. P_request: {1}  P_engine_drag: {2}",
+						_currentState.AbsTime, requestedEnginePower, _currentState.FullDragPower);
+				}
+				return _currentState.FullDragPower;
+			}
+			return requestedEnginePower;
+		}
+
+		public IList<string> Warnings()
+		{
+			IList<string> retVal = new List<string>();
+			retVal.Add(string.Format("Engine power corrected (>5%) in {0} time steps ", _enginePowerCorrections.Count));
+			return retVal;
+		}
+	}
+}
\ No newline at end of file
diff --git a/VectoCore/Models/SimulationComponent/Impl/Vehicle.cs b/VectoCore/Models/SimulationComponent/Impl/Vehicle.cs
index 79f1768705..e8ec0490a1 100644
--- a/VectoCore/Models/SimulationComponent/Impl/Vehicle.cs
+++ b/VectoCore/Models/SimulationComponent/Impl/Vehicle.cs
@@ -22,8 +22,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		public Vehicle(VehicleContainer container, VehicleData data) : base(container)
 		{
 			_data = data;
-			_previousState = new VehicleState { Velocity = 0.SI<MeterPerSecond>() };
-			_currentState = new VehicleState();
+			_previousState = new VehicleState() { Distance = 0.SI<Meter>(), Velocity = 0.SI<MeterPerSecond>() };
+			_currentState = new VehicleState() { Distance = 0.SI<Meter>(), Velocity = 0.SI<MeterPerSecond>() };
 		}
 
 		public Vehicle(VehicleContainer container, VehicleData data, double initialVelocity) : this(container, data)
@@ -49,7 +49,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		protected override void DoWriteModalResults(IModalDataWriter writer)
 		{
 			writer[ModalResultField.v_act] = (_previousState.Velocity + _currentState.Velocity) / 2;
-			writer[ModalResultField.dist] = (_previousState.Distance - _currentState.Distance) / 2;
+			writer[ModalResultField.dist] = _currentState.Distance;
 
 			// hint: take care to use correct velocity when writing the P... values in moddata
 		}
@@ -65,7 +65,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		{
 			_currentState.Velocity = (_previousState.Velocity + (accelleration * dt)).Cast<MeterPerSecond>();
 			_currentState.dt = dt;
-			_currentState.Distance = ((_previousState.Velocity + _currentState.Velocity) / 2 * _currentState.dt).Cast<Meter>();
+			_currentState.Distance = _previousState.Distance +
+									((_previousState.Velocity + _currentState.Velocity) / 2 * _currentState.dt).Cast<Meter>();
 
 			// DriverAcceleration = vehicleAccelerationForce - RollingResistance - AirDragResistance - SlopeResistance
 			var vehicleAccelerationForce = DriverAcceleration(accelleration) + RollingResistance(gradient) +
diff --git a/VectoCore/VectoCore.csproj b/VectoCore/VectoCore.csproj
index d14efc363d..89a35be5d8 100644
--- a/VectoCore/VectoCore.csproj
+++ b/VectoCore/VectoCore.csproj
@@ -158,6 +158,7 @@
     <Compile Include="Models\Declaration\MissionType.cs" />
     <Compile Include="Models\SimulationComponent\Data\Engine\PT1Curve.cs" />
     <Compile Include="Models\SimulationComponent\IDrivingCycleInfo.cs" />
+    <Compile Include="Models\SimulationComponent\Impl\EngineOnlyCombustionEngine.cs" />
     <Compile Include="Models\SimulationComponent\Impl\MappingAuxiliaryData.cs" />
     <Compile Include="Models\Simulation\Data\AuxiliaryDemandType.cs" />
     <Compile Include="Models\SimulationComponent\Data\AuxiliaryType.cs" />
diff --git a/VectoCoreTest/Integration/EngineOnlyCycle/EngineOnlyCycleTest.cs b/VectoCoreTest/Integration/EngineOnlyCycle/EngineOnlyCycleTest.cs
index 54eb359f97..028b290891 100644
--- a/VectoCoreTest/Integration/EngineOnlyCycle/EngineOnlyCycleTest.cs
+++ b/VectoCoreTest/Integration/EngineOnlyCycle/EngineOnlyCycleTest.cs
@@ -4,6 +4,7 @@ using System.Linq;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
 using TUGraz.VectoCore.FileIO.Reader;
 using TUGraz.VectoCore.FileIO.Reader.Impl;
+using TUGraz.VectoCore.Models.Connector.Ports.Impl;
 using TUGraz.VectoCore.Models.Simulation.Data;
 using TUGraz.VectoCore.Models.Simulation.Impl;
 using TUGraz.VectoCore.Models.SimulationComponent.Impl;
@@ -34,7 +35,7 @@ namespace TUGraz.VectoCore.Tests.Integration.EngineOnlyCycle
 			aux.AddDirect(cycle);
 			var gearbox = new EngineOnlyGearbox(vehicle);
 
-			var engine = new CombustionEngine(vehicle, engineData);
+			var engine = new EngineOnlyCombustionEngine(vehicle, engineData);
 
 			aux.InPort().Connect(engine.OutPort());
 			gearbox.InPort().Connect(aux.OutPort());
@@ -47,7 +48,8 @@ namespace TUGraz.VectoCore.Tests.Integration.EngineOnlyCycle
 			var dataWriter = new ModalDataWriter(modFile, true);
 
 			foreach (var cycleEntry in data.Entries) {
-				port.Request(absTime, dt, cycleEntry.EngineTorque, cycleEntry.EngineSpeed);
+				var response = port.Request(absTime, dt, cycleEntry.EngineTorque, cycleEntry.EngineSpeed);
+				Assert.IsInstanceOfType(response, typeof(ResponseSuccess));
 				foreach (var sc in vehicle.SimulationComponents()) {
 					dataWriter[ModalResultField.time] = absTime + dt / 2;
 					sc.CommitSimulationStep(dataWriter);
diff --git a/VectoCoreTest/Integration/SimulationRuns/MinimalPowertrain.cs b/VectoCoreTest/Integration/SimulationRuns/MinimalPowertrain.cs
index 383b76a83e..5d558fca7e 100644
--- a/VectoCoreTest/Integration/SimulationRuns/MinimalPowertrain.cs
+++ b/VectoCoreTest/Integration/SimulationRuns/MinimalPowertrain.cs
@@ -159,74 +159,6 @@ namespace TUGraz.VectoCore.Tests.Integration.SimulationRuns
 		}
 
 
-		[TestMethod]
-		public void TestWheelsAndEngineOverload()
-		{
-			var engineData = EngineeringModeSimulationDataReader.CreateEngineDataFromFile(EngineFile);
-			var cycleData = DrivingCycleDataReader.ReadFromFileDistanceBased(CycleFile);
-
-
-			var vehicleData = CreateVehicleData(50000.SI<Kilogram>());
-
-			var driverData = CreateDriverData();
-
-			var modalWriter = new ModalDataWriter("Coach_MinimalPowertrainOverload.vmod", false); //new TestModalDataWriter();
-			var sumWriter = new TestSumWriter();
-			var vehicleContainer = new VehicleContainer(modalWriter, sumWriter);
-
-			var cycle = new DistanceBasedDrivingCycle(vehicleContainer, cycleData);
-
-			dynamic tmp = AddComponent(cycle, new Driver(vehicleContainer, driverData));
-			tmp = AddComponent(tmp, new Vehicle(vehicleContainer, vehicleData));
-			tmp = AddComponent(tmp, new Wheels(vehicleContainer, vehicleData.DynamicTyreRadius));
-			tmp = AddComponent(tmp, new Clutch(vehicleContainer, engineData));
-			AddComponent(tmp, new CombustionEngine(vehicleContainer, engineData));
-
-			var gbx = new DummyGearbox(vehicleContainer);
-
-			var cyclePort = cycle.OutPort();
-
-			cyclePort.Initialize();
-
-			gbx.CurrentGear = 0;
-
-			var absTime = 0.SI<Second>();
-			var response = cyclePort.Request(absTime, 1.SI<Meter>());
-
-			Assert.IsInstanceOfType(response, typeof(ResponseSuccess));
-
-			vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval);
-			absTime += response.SimulationInterval;
-
-			gbx.CurrentGear = 1;
-			var ds = Constants.SimulationSettings.DriveOffDistance;
-			while (vehicleContainer.Distance().Value() < 200) {
-				response = cyclePort.Request(absTime, ds);
-
-				switch (response.ResponseType) {
-					case ResponseType.DrivingCycleDistanceExceeded:
-						var rsp = response as ResponseDrivingCycleDistanceExceeded;
-						ds = rsp.MaxDistance;
-						continue;
-				}
-				Assert.IsInstanceOfType(response, typeof(ResponseSuccess));
-
-
-				vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval);
-				absTime += response.SimulationInterval;
-
-				ds = vehicleContainer.VehicleSpeed().IsEqual(0)
-					? Constants.SimulationSettings.DriveOffDistance
-					: (Constants.SimulationSettings.TargetTimeInterval * vehicleContainer.VehicleSpeed()).Cast<Meter>();
-
-				modalWriter.Finish();
-			}
-
-			modalWriter.Finish();
-			//var run = new DistanceRun(vehicleContainer);
-			//run.Run();
-		}
-
 		private static VehicleData CreateVehicleData(Kilogram loading)
 		{
 			var axles = new List<Axle>() {
diff --git a/VectoCoreTest/Models/SimulationComponent/CombustionEngineTest.cs b/VectoCoreTest/Models/SimulationComponent/CombustionEngineTest.cs
index 9d19fb3278..cddadc4317 100644
--- a/VectoCoreTest/Models/SimulationComponent/CombustionEngineTest.cs
+++ b/VectoCoreTest/Models/SimulationComponent/CombustionEngineTest.cs
@@ -148,7 +148,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent
 			var engineData =
 				EngineeringModeSimulationDataReader.CreateEngineDataFromFile(
 					TestContext.DataRow["EngineFile"].ToString());
-			var engine = new CombustionEngine(vehicleContainer, engineData);
+			var engine = new EngineOnlyCombustionEngine(vehicleContainer, engineData);
 
 			gearbox.InPort().Connect(engine.OutPort());
 
diff --git a/VectoCoreTest/Models/SimulationComponent/DistanceBasedDrivingCycleTest.cs b/VectoCoreTest/Models/SimulationComponent/DistanceBasedDrivingCycleTest.cs
index 00a23ad32a..c8b1723fff 100644
--- a/VectoCoreTest/Models/SimulationComponent/DistanceBasedDrivingCycleTest.cs
+++ b/VectoCoreTest/Models/SimulationComponent/DistanceBasedDrivingCycleTest.cs
@@ -1,6 +1,7 @@
 using System;
 using System.Linq;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
+using TUGraz.VectoCore.Configuration;
 using TUGraz.VectoCore.Exceptions;
 using TUGraz.VectoCore.FileIO.Reader;
 using TUGraz.VectoCore.FileIO.Reader.Impl;
@@ -23,6 +24,8 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent
 		[TestMethod]
 		public void TestDistanceRequest()
 		{
+			// Constants.SimulationSettings.DrivingCycleRoadGradientTolerance = 1E-12;
+
 			var cycleData = DrivingCycleDataReader.ReadFromFile(ShortCycle, DrivingCycleData.CycleType.DistanceBased);
 
 			var vehicleContainer = new VehicleContainer();
@@ -52,7 +55,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent
 			Assert.IsInstanceOfType(response, typeof(ResponseSuccess));
 
 			Assert.AreEqual(5.SI<MeterPerSecond>().Value(), driver.LastRequest.TargetVelocity.Value(), Tolerance);
-			Assert.AreEqual(0.02667562971628240, driver.LastRequest.Gradient.Value(), 1E-12);
+			Assert.AreEqual(0.0284160694958265, driver.LastRequest.Gradient.Value(), 1E-12);
 			Assert.AreEqual(1 + startDistance, cycle.CurrentState.Distance.Value(), Tolerance);
 
 			vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval);
@@ -64,7 +67,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent
 			Assert.IsInstanceOfType(response, typeof(ResponseSuccess));
 
 			Assert.AreEqual(5.SI<MeterPerSecond>().Value(), driver.LastRequest.TargetVelocity.Value(), Tolerance);
-			Assert.AreEqual(0.02667562971628240, driver.LastRequest.Gradient.Value(), 1E-12);
+			Assert.AreEqual(0.0284160694958265, driver.LastRequest.Gradient.Value(), 1E-12);
 			Assert.AreEqual(2 + startDistance, cycle.CurrentState.Distance.Value(), Tolerance);
 
 			vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval);
@@ -75,10 +78,10 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent
 
 			Assert.IsInstanceOfType(response, typeof(ResponseDrivingCycleDistanceExceeded));
 			var tmp = response as ResponseDrivingCycleDistanceExceeded;
-			Assert.AreEqual(36, tmp.MaxDistance.Value(), Tolerance);
+			Assert.AreEqual(16, tmp.MaxDistance.Value(), Tolerance);
 
 			Assert.AreEqual(5.SI<MeterPerSecond>().Value(), driver.LastRequest.TargetVelocity.Value(), Tolerance);
-			Assert.AreEqual(0.02667562971628240, driver.LastRequest.Gradient.Value(), 1E-12);
+			Assert.AreEqual(0.0284160694958265, driver.LastRequest.Gradient.Value(), 1E-12);
 			Assert.AreEqual(2 + startDistance, cycle.CurrentState.Distance.Value(), Tolerance);
 
 			try {
@@ -91,8 +94,8 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent
 			response = cycle.OutPort().Request(absTime, tmp.MaxDistance);
 
 			Assert.AreEqual(5.SI<MeterPerSecond>().Value(), driver.LastRequest.TargetVelocity.Value(), Tolerance);
-			Assert.AreEqual(0.02667562971628240, driver.LastRequest.Gradient.Value(), 1E-12);
-			Assert.AreEqual(38 + startDistance, cycle.CurrentState.Distance.Value(), Tolerance);
+			Assert.AreEqual(0.0284160694958265, driver.LastRequest.Gradient.Value(), 1E-12);
+			Assert.AreEqual(18 + startDistance, cycle.CurrentState.Distance.Value(), Tolerance);
 
 
 			vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval);
-- 
GitLab