diff --git a/VectoCore/Models/SimulationComponent/Data/Engine/FullLoadCurve.cs b/VectoCore/Models/SimulationComponent/Data/Engine/FullLoadCurve.cs index ae2aee95275e2e51398a4db34739984759988097..9ed51dfa2d8848858ee58475e3d15a198a9dbd71 100644 --- a/VectoCore/Models/SimulationComponent/Data/Engine/FullLoadCurve.cs +++ b/VectoCore/Models/SimulationComponent/Data/Engine/FullLoadCurve.cs @@ -55,28 +55,28 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine return fullLoadCurve; } - public double FullLoadStaticTorque(double rpm) + public double FullLoadStationaryTorque(double rpm) { var idx = FindIndexForRpm(rpm); return VectoMath.Interpolate(entries[idx - 1].EngineSpeed, entries[idx].EngineSpeed, entries[idx - 1].TorqueFullLoad, entries[idx].TorqueFullLoad, rpm); } - public double FullLoadStaticPower(double rpm) + public double FullLoadStationaryPower(double rpm) { - return VectoMath.ConvertRpmToPower(rpm, FullLoadStaticTorque(rpm)); + return VectoMath.ConvertRpmToPower(rpm, FullLoadStationaryTorque(rpm)); } - public double DragLoadStaticTorque(double rpm) + public double DragLoadStationaryTorque(double rpm) { var idx = FindIndexForRpm(rpm); return VectoMath.Interpolate(entries[idx - 1].EngineSpeed, entries[idx].EngineSpeed, entries[idx - 1].TorqueDrag, entries[idx].TorqueDrag, rpm); } - public double DragLoadStaticPower(double rpm) + public double DragLoadStationaryPower(double rpm) { - return VectoMath.ConvertRpmToPower(rpm, DragLoadStaticTorque(rpm)); + return VectoMath.ConvertRpmToPower(rpm, DragLoadStationaryTorque(rpm)); } public double PT1(double rpm) @@ -90,7 +90,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine { int idx; if (rpm < entries[0].EngineSpeed) { - Logger.ErrorFormat("requested rpm below minimum rpm in FLD curve - extrapolating. n: {0}, rpm_min: {1}", rpm, + Log.ErrorFormat("requested rpm below minimum rpm in FLD curve - extrapolating. n: {0}, rpm_min: {1}", rpm, entries[0].EngineSpeed); idx = 1; } else { @@ -99,6 +99,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine if (idx <= 0) { idx = 1; } + return idx; } } } diff --git a/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs b/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs index 54c41786eef65c683979fdf2d2c79801854228b5..813055b31761dc942f5d6e9d7ed517e66d0f44eb 100644 --- a/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs +++ b/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs @@ -1,11 +1,8 @@ using System; using System.Collections.Generic; -using NLog; -using NLog.Layouts; using TUGraz.VectoCore.Exceptions; using TUGraz.VectoCore.Models.Connector.Ports; using TUGraz.VectoCore.Models.SimulationComponent.Data; -using TUGraz.VectoCore.Models.SimulationComponent.Data.Engine; using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.SimulationComponent.Impl @@ -14,6 +11,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl public class CombustionEngine : VectoSimulationComponent, ICombustionEngine, ITnOutPort { private const int EngineIdleSpeedStopThreshold = 100; + private const double MaxPowerExceededThreshold = 1.05; + private const double ZeroThreshold = 0.0001; + private const double FullLoadMargin = 0.01; public enum EngineOperationMode { @@ -63,47 +63,73 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl if (engineSpeed < _data.IdleSpeed - EngineIdleSpeedStopThreshold) { _currentState.OperationMode = EngineOperationMode.Stopped; - _currentState.EnginePowerLoss = enginePowerLoss - } + _currentState.EnginePowerLoss = enginePowerLoss; + } uint currentGear = 0; // TODO: get current Gear from Vehicle! - var minEnginePower = _data.GetFullLoadCurve(currentGear).DragLoadStaticPower(engineSpeed); + 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))); + throw new VectoSimulationException(String.Format("t: {0} P_engine_full < 0! n: {1} [1/min] ", absTime, engineSpeed)); } if (requestedPower > maxEnginePower) { - if (requestedEnginePower/maxEnginePower > 1.05) { + 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 > 1.05 && requestedEnginePower > -99999) { + 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); } } - //throw new NotImplementedException(); + if (requestedEnginePower < -ZeroThreshold) { + _currentState.OperationMode = IsFullLoad(requestedEnginePower, maxEnginePower) + ? EngineOperationMode.FullLoad + : EngineOperationMode.Load; + } + else if (requestedPower > ZeroThreshold) { + _currentState.OperationMode = IsFullLoad(requestedEnginePower, maxEnginePower) + ? EngineOperationMode.FullDrag + : EngineOperationMode.Drag; + } + else { + // -ZeroThreshold <= requestedEnginePower <= ZeroThreshold + _currentState.OperationMode = EngineOperationMode.Idle; + } } + 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; + } + protected double FullLoadPowerDyamic(uint gear, double rpm) { - var staticFullLoadPower = _data.GetFullLoadCurve(gear).FullLoadStaticPower(rpm); + var staticFullLoadPower = _data.GetFullLoadCurve(gear).FullLoadStationaryPower(rpm); var pt1 = _data.GetFullLoadCurve(gear).PT1(rpm); return Math.Min( (1 / (pt1 + 1)) * (staticFullLoadPower + pt1 * _previousState.EnginePower), staticFullLoadPower); } + protected bool IsFullLoad(double requestedPower, double maxPower) + { + return Math.Abs(requestedPower / maxPower - 1.0) < FullLoadMargin; + } + protected double InertiaPowerLoss(double torque, double engineSpeed) { diff --git a/VectoCore/Utils/VectoMath.cs b/VectoCore/Utils/VectoMath.cs index 24113d5ee8fd414e266d53017a1bc48a335384b3..6a13ab40edfccb233bffb535c99b98d4256bdd45 100644 --- a/VectoCore/Utils/VectoMath.cs +++ b/VectoCore/Utils/VectoMath.cs @@ -27,7 +27,7 @@ namespace TUGraz.VectoCore.Utils /// <returns>the power equivalent to the given rpm and torque [W]</returns> public static double ConvertRpmToPower(double rpm, double torque) { - return (2.0 * Math.PI / 60.0) * torque * rpm + return (2.0 * Math.PI / 60.0) * torque * rpm; } } } \ No newline at end of file diff --git a/VectoCoreTest/Models/SimulationComponentData/FullLoadCurveTest.cs b/VectoCoreTest/Models/SimulationComponentData/FullLoadCurveTest.cs new file mode 100644 index 0000000000000000000000000000000000000000..9f56e2640f82b0823f707ec7d93e46fd45988187 --- /dev/null +++ b/VectoCoreTest/Models/SimulationComponentData/FullLoadCurveTest.cs @@ -0,0 +1,71 @@ +using System; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using TUGraz.VectoCore.Models.SimulationComponent.Data.Engine; + +namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData +{ + [TestClass] + public class FullLoadCurveTest + { + private static string CoachEngineFLD = "TestData\\EngineOnly\\EngineMaps\\24t Coach.vfld"; + private static double tolerance = 0.0001; + + [TestMethod] + public void TestFullLoadStaticTorque() + { + FullLoadCurve fldCurve = FullLoadCurve.ReadFromFile(CoachEngineFLD); + + Assert.AreEqual(1180, fldCurve.FullLoadStationaryTorque(560.0), tolerance); + Assert.AreEqual(1352, fldCurve.FullLoadStationaryTorque(2000), tolerance); + + Assert.AreEqual(1231, fldCurve.FullLoadStationaryTorque(580), tolerance); + } + + [TestMethod] + public void TestFullLoadStaticPower() + { + FullLoadCurve fldCurve = FullLoadCurve.ReadFromFile(CoachEngineFLD); + + Assert.AreEqual( 69198.814183, fldCurve.FullLoadStationaryPower(560.0), tolerance); + Assert.AreEqual(283162.218372, fldCurve.FullLoadStationaryPower(2000), tolerance); + + Assert.AreEqual( 74767.810760, fldCurve.FullLoadStationaryPower(580), tolerance); + + } + + [TestMethod] + public void TestDragLoadStaticTorque() + { + FullLoadCurve fldCurve = FullLoadCurve.ReadFromFile(CoachEngineFLD); + + Assert.AreEqual(-149, fldCurve.DragLoadStationaryTorque(560.0), tolerance); + Assert.AreEqual(-301, fldCurve.DragLoadStationaryTorque(2000), tolerance); + + Assert.AreEqual(-148.5, fldCurve.DragLoadStationaryTorque(580), tolerance); + + } + + [TestMethod] + public void TestDragLoadStaticPower() + { + FullLoadCurve fldCurve = FullLoadCurve.ReadFromFile(CoachEngineFLD); + + Assert.AreEqual( -8737.81636, fldCurve.DragLoadStationaryPower(560.0), tolerance); + Assert.AreEqual(-63041.29254, fldCurve.DragLoadStationaryPower(2000), tolerance); + + Assert.AreEqual(-9019.51251, fldCurve.DragLoadStationaryPower(580), tolerance); + } + + [TestMethod] + public void TestPT1() + { + FullLoadCurve fldCurve = FullLoadCurve.ReadFromFile(CoachEngineFLD); + + Assert.AreEqual(0.6, fldCurve.PT1(560.0), tolerance); + Assert.AreEqual(0.25, fldCurve.PT1(2000), tolerance); + + Assert.AreEqual(0.37, fldCurve.PT1(1700), tolerance); + + } + } +} diff --git a/VectoCoreTest/VectoCoreTest.csproj b/VectoCoreTest/VectoCoreTest.csproj index a657bf45fc93214ff767cfd2e4d7d46b2280d03f..5f4ac6c100d0d388e729182d241cea3c81e015cf 100644 --- a/VectoCoreTest/VectoCoreTest.csproj +++ b/VectoCoreTest/VectoCoreTest.csproj @@ -67,6 +67,7 @@ </Otherwise> </Choose> <ItemGroup> + <Compile Include="Models\SimulationComponentData\FullLoadCurveTest.cs" /> <Compile Include="Models\SimulationComponent\CombustionEngineTest.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\Settings.Designer.cs"> @@ -111,9 +112,7 @@ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> </ItemGroup> - <ItemGroup> - <Folder Include="TestData\EngineOnly\ResultFiles\" /> - </ItemGroup> + <ItemGroup /> <Choose> <When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'"> <ItemGroup>