From 142052212074451bd99ac3bafa74ee2d05d3f398 Mon Sep 17 00:00:00 2001
From: Markus Quaritsch <markus.quaritsch@tugraz.at>
Date: Thu, 12 Mar 2015 17:01:09 +0100
Subject: [PATCH] more work on engine model, implementing first testcases

---
 .gitignore                                    |  3 +-
 .../Data/CombustionEngineData.cs              |  1 +
 .../Data/Engine/FullLoadCurve.cs              |  2 +-
 .../Impl/CombustionEngine.cs                  | 91 +++++++++++++------
 VectoCore/Utils/VectoMath.cs                  |  5 +
 .../CombustionEngineTest.cs                   | 32 ++++---
 .../FullLoadCurveTest.cs                      |  9 +-
 VectoCoreTest/Utils/TestModalDataWriter.cs    |  4 +-
 8 files changed, 101 insertions(+), 46 deletions(-)

diff --git a/.gitignore b/.gitignore
index 5464d948ea..eb85b28f04 100644
--- a/.gitignore
+++ b/.gitignore
@@ -187,4 +187,5 @@ UpgradeLog*.htm
 *.bim_*.settings
 
 # Microsoft Fakes
-FakesAssemblies/
\ No newline at end of file
+FakesAssemblies/
+VectoCoreTest/TestData/EngineOnly/Test1/Test1_results.vmod.csv
diff --git a/VectoCore/Models/SimulationComponent/Data/CombustionEngineData.cs b/VectoCore/Models/SimulationComponent/Data/CombustionEngineData.cs
index 2ba69b556e..148cebdd74 100644
--- a/VectoCore/Models/SimulationComponent/Data/CombustionEngineData.cs
+++ b/VectoCore/Models/SimulationComponent/Data/CombustionEngineData.cs
@@ -203,6 +203,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
 
         public FullLoadCurve GetFullLoadCurve(uint gear)
         {
+			// TODO: @@@quam refactor
             foreach (var gearRange in _fullLoadCurves.Keys)
             {
                 var low = uint.Parse(gearRange.Split('-').First().Trim());
diff --git a/VectoCore/Models/SimulationComponent/Data/Engine/FullLoadCurve.cs b/VectoCore/Models/SimulationComponent/Data/Engine/FullLoadCurve.cs
index 9ed51dfa2d..af54d8af7f 100644
--- a/VectoCore/Models/SimulationComponent/Data/Engine/FullLoadCurve.cs
+++ b/VectoCore/Models/SimulationComponent/Data/Engine/FullLoadCurve.cs
@@ -97,7 +97,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine
 				idx = entries.FindIndex(x => x.EngineSpeed > rpm);
 			}
 			if (idx <= 0) {
-				idx = 1;
+				idx = rpm > entries[0].EngineSpeed ? entries.Count - 1 : 1;
 			}
 		    return idx;
 	    }
diff --git a/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs b/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs
index 813055b317..21d625f555 100644
--- a/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs
+++ b/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs
@@ -50,13 +50,16 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 
 	    public override void CommitSimulationStep(IModalDataWriter writer)
 	    {
-	        writer[ModalResultField.FC] = 1;
-	        writer[ModalResultField.FCAUXc] = 2;
-            writer[ModalResultField.FCWHTCc] = 3;
+		    writer[ModalResultField.PaEng] = _currentState.EnginePowerLoss;
+		    _previousState = _currentState;
+			_currentState = new EngineState();
 	    }
 
         public void Request(TimeSpan absTime, TimeSpan dt, double torque, double engineSpeed)
         {
+	        _currentState.EngineSpeed = engineSpeed;
+	        _currentState.AbsTime = absTime;
+
 			var requestedPower = VectoMath.ConvertRpmToPower(engineSpeed, torque);
 			var enginePowerLoss = InertiaPowerLoss(torque, engineSpeed);
 			var requestedEnginePower = requestedPower + enginePowerLoss;
@@ -71,43 +74,69 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 	        var minEnginePower = _data.GetFullLoadCurve(currentGear).DragLoadStationaryPower(engineSpeed);
 	        var maxEnginePower = FullLoadPowerDyamic(currentGear, engineSpeed);
 
-	        if (minEnginePower >= 0 && requestedPower < 0) {
-		        throw new VectoSimulationException(String.Format("t: {0}  P_engine_drag > 0! n: {1} [1/min] ", absTime, engineSpeed));
-	        }
-	        if (maxEnginePower <= 0 && requestedPower > 0) {
-		        throw new VectoSimulationException(String.Format("t: {0}  P_engine_full < 0! n: {1} [1/min] ", absTime, engineSpeed));
-	        }
+			ValidatePowerDemand(requestedEnginePower, maxEnginePower, minEnginePower);
+
+	        requestedEnginePower = LimitEnginePower(requestedEnginePower, maxEnginePower, minEnginePower);
+
+			UpdateEngineState(requestedEnginePower, maxEnginePower, minEnginePower);
+        }
+
+		protected void ValidatePowerDemand(double requestedEnginePower, double maxEnginePower, double minEnginePower)
+		{
+			if (minEnginePower >= 0 && requestedEnginePower < 0)
+			{
+				throw new VectoSimulationException(String.Format("t: {0}  P_engine_drag > 0! n: {1} [1/min] ", _currentState.AbsTime, _currentState.EngineSpeed));
+			}
+			if (maxEnginePower <= 0 && requestedEnginePower > 0)
+			{
+				throw new VectoSimulationException(String.Format("t: {0}  P_engine_full < 0! n: {1} [1/min] ", _currentState.AbsTime, _currentState.EngineSpeed));
+			}
+		}
 
-	        if (requestedPower > maxEnginePower) {
+		protected double LimitEnginePower(double requestedEnginePower, double maxEnginePower, double minEnginePower)
+		{
+			if (requestedEnginePower > maxEnginePower)
+			{
 				if (requestedEnginePower / maxEnginePower > MaxPowerExceededThreshold)
 				{
-			        requestedEnginePower = maxEnginePower;
-					_enginePowerCorrections.Add(absTime);
-					Log.WarnFormat("t: {0}  requested power > P_engine_full * 1.05 - corrected. P_request: {1}  P_engine_full: {2}", absTime, requestedEnginePower, maxEnginePower);
-		        }
-	        } else if (requestedPower < minEnginePower) {
-		        if (requestedEnginePower/minEnginePower > MaxPowerExceededThreshold && requestedEnginePower > -99999) {
-			        requestedEnginePower = minEnginePower;
-					_enginePowerCorrections.Add(absTime);
-					Log.WarnFormat("t: {0}  requested power < P_engine_drag * 1.05 - corrected. P_request: {1}  P_engine_drag: {2}", absTime, requestedEnginePower, minEnginePower);
-		        }
-	        }
-
-	        if (requestedEnginePower < -ZeroThreshold) {
-		        _currentState.OperationMode = IsFullLoad(requestedEnginePower, maxEnginePower)
-			        ? EngineOperationMode.FullLoad
-			        : EngineOperationMode.Load;
-	        }
-			else if (requestedPower > ZeroThreshold) {
+					_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, maxEnginePower);
+					return maxEnginePower;
+				}
+			}
+			else if (requestedEnginePower < minEnginePower)
+			{
+				if (requestedEnginePower / minEnginePower > 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, minEnginePower);
+					return minEnginePower;
+				}
+			}
+			return requestedEnginePower;
+
+		}
+
+		protected void UpdateEngineState(double requestedEnginePower, double maxEnginePower, double minEnginePower)
+		{
+			if (requestedEnginePower < -ZeroThreshold)
+			{
 				_currentState.OperationMode = IsFullLoad(requestedEnginePower, maxEnginePower)
+					? EngineOperationMode.FullLoad
+					: EngineOperationMode.Load;
+			}
+			else if (requestedEnginePower > ZeroThreshold)
+			{
+				_currentState.OperationMode = IsFullLoad(requestedEnginePower, minEnginePower)
 					? EngineOperationMode.FullDrag
 					: EngineOperationMode.Drag;
 			}
-			else {
+			else
+			{
 				// -ZeroThreshold <= requestedEnginePower <= ZeroThreshold
 				_currentState.OperationMode = EngineOperationMode.Idle;
 			}
-        }
+		}
 
 		public IList<string> Warnings()
 		{
@@ -147,6 +176,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 				public double EnginePower { get; set; }
 				public double EngineSpeed { get; set; }
 				public double EnginePowerLoss { get; set; }
+
+				public TimeSpan AbsTime { get; set; }
 			}
 	}
 
diff --git a/VectoCore/Utils/VectoMath.cs b/VectoCore/Utils/VectoMath.cs
index 6a13ab40ed..1475c14e9f 100644
--- a/VectoCore/Utils/VectoMath.cs
+++ b/VectoCore/Utils/VectoMath.cs
@@ -29,5 +29,10 @@ namespace TUGraz.VectoCore.Utils
 		{
 			return (2.0 * Math.PI / 60.0) * torque * rpm;
 		}
+
+		public static double ConvertPowerToTorque(double power, double rpm)
+		{
+			return power / ((2.0 * Math.PI / 60.0) * rpm);
+		}
 	}
 }
\ No newline at end of file
diff --git a/VectoCoreTest/Models/SimulationComponent/CombustionEngineTest.cs b/VectoCoreTest/Models/SimulationComponent/CombustionEngineTest.cs
index cecf1cd2f7..f58efb4494 100644
--- a/VectoCoreTest/Models/SimulationComponent/CombustionEngineTest.cs
+++ b/VectoCoreTest/Models/SimulationComponent/CombustionEngineTest.cs
@@ -1,12 +1,14 @@
 using System;
 using System.Data;
 using System.IO;
+using System.Net.Security;
 using System.Reflection;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
 using TUGraz.VectoCore.Models.Connector.Ports;
 using TUGraz.VectoCore.Models.SimulationComponent.Data;
 using TUGraz.VectoCore.Models.SimulationComponent.Impl;
 using TUGraz.VectoCore.Tests.Utils;
+using TUGraz.VectoCore.Utils;
 
 namespace TUGraz.VectoCore.Tests.Models.SimulationComponent
 {
@@ -14,6 +16,8 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent
     [TestClass]
     public class CombustionEngineTest
     {
+		private const string CoachEngine = "TestData\\EngineOnly\\EngineMaps\\24t Coach.veng";
+
 		public TestContext TestContext { get; set; }
 
         [ClassInitialize]
@@ -26,7 +30,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent
         [TestMethod]
         public void TestEngineHasOutPort()
         {
-            var engineData = CombustionEngineData.ReadFromFile("TestData\\EngineOnly\\EngineMaps\\24t Coach.veng");
+            var engineData = CombustionEngineData.ReadFromFile(CoachEngine);
             var engine = new CombustionEngine(engineData);
 
             var port = engine.OutShaft();
@@ -36,7 +40,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent
         [TestMethod]
         public void TestOutPortRequestNotFailing()
         {
-			var engineData = CombustionEngineData.ReadFromFile("TestData\\EngineOnly\\EngineMaps\\24t Coach.veng");
+			var engineData = CombustionEngineData.ReadFromFile(CoachEngine);
             var engine = new CombustionEngine(engineData);
 
             var port = engine.OutShaft();
@@ -52,7 +56,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent
         [TestMethod]
         public void TestSimpleModalData()
         {
-			var engineData = CombustionEngineData.ReadFromFile("TestData\\EngineOnly\\EngineMaps\\24t Coach.veng");
+			var engineData = CombustionEngineData.ReadFromFile(CoachEngine);
             var engine = new CombustionEngine(engineData);
             var port = engine.OutShaft();
 
@@ -60,18 +64,24 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent
             var dt = new TimeSpan(seconds: 1, minutes: 0, hours: 0);
 
             //todo: set correct input values to test
-            var torque = 400.0;
-            var engineSpeed = 1500.0;
-            port.Request(absTime, dt, torque, engineSpeed);
+            var torque = 0.0;
+            var engineSpeed = 600.0;
+			var dataWriter = new TestModalDataWriter();
 
+	        for (var i = 0; i < 10; i++) {
+		        port.Request(absTime, dt, torque, engineSpeed);
+				engine.CommitSimulationStep(dataWriter);
+				absTime += dt;
+	        }
 
-            var dataWriter = new TestModalDataWriter();
-            engine.CommitSimulationStep(dataWriter);
+			port.Request(absTime, dt, VectoMath.ConvertPowerToTorque(2329.973, 644.4445), 644.4445);
+			engine.CommitSimulationStep(dataWriter);
 
             //todo: test with correct output values, add other fields to test
-            Assert.AreEqual(dataWriter[ModalResultField.FC], 13000);
-            Assert.AreEqual(dataWriter[ModalResultField.FCAUXc], 14000);
-            Assert.AreEqual(dataWriter[ModalResultField.FCWHTCc], 15000);
+            //Assert.AreEqual(dataWriter[ModalResultField.FC], 13000);
+            //Assert.AreEqual(dataWriter[ModalResultField.FCAUXc], 14000);
+            //Assert.AreEqual(dataWriter[ModalResultField.FCWHTCc], 15000);
+			Assert.AreEqual(2.906175, dataWriter[ModalResultField.PaEng]);
         }
 
 		[DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", "|DataDirectory|\\TestData\\EngineTests.csv", "EngineTests#csv", DataAccessMethod.Sequential)]
diff --git a/VectoCoreTest/Models/SimulationComponentData/FullLoadCurveTest.cs b/VectoCoreTest/Models/SimulationComponentData/FullLoadCurveTest.cs
index 9f56e2640f..a64cace5f5 100644
--- a/VectoCoreTest/Models/SimulationComponentData/FullLoadCurveTest.cs
+++ b/VectoCoreTest/Models/SimulationComponentData/FullLoadCurveTest.cs
@@ -19,6 +19,8 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData
 			Assert.AreEqual(1352, fldCurve.FullLoadStationaryTorque(2000), tolerance);
 
 			Assert.AreEqual(1231, fldCurve.FullLoadStationaryTorque(580), tolerance);
+
+
 		}
 
 		[TestMethod]
@@ -42,7 +44,12 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData
 			Assert.AreEqual(-301, fldCurve.DragLoadStationaryTorque(2000), tolerance);
 
 			Assert.AreEqual(-148.5, fldCurve.DragLoadStationaryTorque(580), tolerance);
-			
+
+			Assert.AreEqual(-150, fldCurve.DragLoadStationaryTorque(520.0), tolerance);
+
+			Assert.AreEqual(-339, fldCurve.DragLoadStationaryTorque(2200.0), tolerance);
+
+
 		}
 
 		[TestMethod]
diff --git a/VectoCoreTest/Utils/TestModalDataWriter.cs b/VectoCoreTest/Utils/TestModalDataWriter.cs
index 53a0ffaf56..05548027a0 100644
--- a/VectoCoreTest/Utils/TestModalDataWriter.cs
+++ b/VectoCoreTest/Utils/TestModalDataWriter.cs
@@ -27,8 +27,8 @@ namespace TUGraz.VectoCore.Tests.Utils
 
         public object this[ModalResultField key]
         {
-            get { return CurrentRow[key.ToString()]; }
-            set { CurrentRow[key.ToString()] = value; }
+            get { return CurrentRow[key.GetName()]; }
+            set { CurrentRow[key.GetName()] = value; }
         }
     }
 }
-- 
GitLab