diff --git a/VectoCore/Models/Declaration/Declaration.cs b/VectoCore/Models/Declaration/Declaration.cs index 8de83ecca43ce4f16919660f0a487b512ba594d1..537818cacafddf020d32461572c47e01e0bfe233 100644 --- a/VectoCore/Models/Declaration/Declaration.cs +++ b/VectoCore/Models/Declaration/Declaration.cs @@ -4,24 +4,26 @@ using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.Declaration { - public class DeclarationRims : LookupData<DeclarationRims.RimsEntry> + public class DeclarationRims : LookupData<DeclarationRims.RimsEntry, string> { - private const string ResourceId = "TUGraz.VectoCore.Resources.Declaration.Rims.csv"; - internal DeclarationRims() { var csvFile = ReadCsvFile(ResourceId); ParseData(csvFile); } + protected override string ResourceId + { + get { return "TUGraz.VectoCore.Resources.Declaration.Rims.csv"; } + } protected override sealed void ParseData(DataTable table) { - _data = (from DataRow row in table.Rows + Data = (from DataRow row in table.Rows select new RimsEntry { RimsType = row[0].ToString(), F_a = row.ParseDouble(1), - F_b = row.ParseDouble(2), + F_b = row.ParseDouble(2) }).ToDictionary(e => e.RimsType); } diff --git a/VectoCore/Models/Declaration/DeclarationData.cs b/VectoCore/Models/Declaration/DeclarationData.cs index a06241fe32e35afed750291a226e62b1dbedc206..d572591c627845ec8e03ecb08a30e03832f1169d 100644 --- a/VectoCore/Models/Declaration/DeclarationData.cs +++ b/VectoCore/Models/Declaration/DeclarationData.cs @@ -1,4 +1,11 @@ -namespace TUGraz.VectoCore.Models.Declaration +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using TUGraz.VectoCore.Exceptions; +using TUGraz.VectoCore.Utils; + +namespace TUGraz.VectoCore.Models.Declaration { public class DeclarationData { @@ -6,6 +13,7 @@ private readonly DeclarationSegments _segments; private readonly DeclarationRims _rims; private readonly DeclarationWheels _wheels; + private readonly DeclarationPT1 _pt1; public static DeclarationWheels Wheels { @@ -22,11 +30,17 @@ get { return Instance()._segments; } } + public static DeclarationPT1 PT1 + { + get { return Instance()._pt1; } + } + private DeclarationData() { _wheels = new DeclarationWheels(); _rims = new DeclarationRims(); _segments = new DeclarationSegments(); + _pt1 = new DeclarationPT1(); } private static DeclarationData Instance() @@ -34,4 +48,43 @@ return _instance ?? (_instance = new DeclarationData()); } } + + public class DeclarationPT1 : LookupData<Second, PerSecond> + { + private List<KeyValuePair<PerSecond, Second>> _entries; + + protected override string ResourceId + { + get { return "TUGraz.VectoCore.Resources.Declaration.PT1.csv"; } + } + + protected override void ParseData(DataTable table) + { + _entries = table.Rows.Cast<DataRow>() + .Select(r => new KeyValuePair<PerSecond, Second>(r.ParseDouble("rpm").RPMtoRad(), r.ParseDouble("PT1").SI<Second>())) + .OrderBy(x => x.Key) + .ToList(); + } + + public override Second Lookup(PerSecond key) + { + var index = 1; + if (key < _entries[0].Key) { + Log.ErrorFormat("requested rpm below minimum rpm in pt1 - extrapolating. n: {0}, rpm_min: {1}", + key.ConvertTo().Rounds.Per.Minute, _entries[0].Key.ConvertTo().Rounds.Per.Minute); + } else { + index = _entries.FindIndex(x => x.Key > key); + if (index <= 0) { + index = (key > _entries[0].Key) ? _entries.Count - 1 : 1; + } + } + + var pt1 = VectoMath.Interpolate(_entries[index - 1].Key, _entries[index].Key, _entries[index - 1].Value, + _entries[index].Value, key); + if (pt1 < 0) { + throw new VectoException("The calculated value must not be smaller than 0. Value: " + pt1); + } + return pt1; + } + } } \ No newline at end of file diff --git a/VectoCore/Models/Declaration/DeclarationWheels.cs b/VectoCore/Models/Declaration/DeclarationWheels.cs index 07e97c9bad7ffc271101114815ce32c514da6b5e..43f4291c161afdedb2d81674c8ddb46ed120d721 100644 --- a/VectoCore/Models/Declaration/DeclarationWheels.cs +++ b/VectoCore/Models/Declaration/DeclarationWheels.cs @@ -5,20 +5,16 @@ using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.Declaration { - public class DeclarationWheels : LookupData<DeclarationWheels.WheelsEntry> + public class DeclarationWheels : LookupData<DeclarationWheels.WheelsEntry, string> { - private const string ResourceId = "TUGraz.VectoCore.Resources.Declaration.Wheels.csv"; - - internal DeclarationWheels() + protected override string ResourceId { - var csvFile = ReadCsvFile(ResourceId); - ParseData(csvFile); + get { return "TUGraz.VectoCore.Resources.Declaration.Wheels.csv"; } } - protected override sealed void ParseData(DataTable table) { - _data = (from DataRow row in table.Rows + Data = (from DataRow row in table.Rows select new WheelsEntry { WheelType = row[0].ToString(), Inertia = row.ParseDouble(1).SI<KilogramSquareMeter>(), diff --git a/VectoCore/Models/Declaration/LookupData.cs b/VectoCore/Models/Declaration/LookupData.cs index 76264ef7546d83a3e4fd9733ebd5fd0f0725b514..260da0ab3413fa3d5e44b07b97e52f2571ea8e23 100644 --- a/VectoCore/Models/Declaration/LookupData.cs +++ b/VectoCore/Models/Declaration/LookupData.cs @@ -2,14 +2,26 @@ using System.Collections.Generic; using System.Data; using System.Reflection; +using Common.Logging; using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.Declaration { - public abstract class LookupData<TEntryType> + public abstract class LookupData<TEntryType, TKeyType> { - protected Dictionary<String, TEntryType> _data; + protected LookupData() + { + Log = LogManager.GetLogger(GetType()); + var csvFile = ReadCsvFile(ResourceId); + ParseData(csvFile); + } + [NonSerialized] protected ILog Log; + + protected abstract string ResourceId { get; } + protected abstract void ParseData(DataTable table); + + protected Dictionary<TKeyType, TEntryType> Data; protected DataTable ReadCsvFile(string resourceId) { @@ -18,13 +30,11 @@ namespace TUGraz.VectoCore.Models.Declaration return VectoCSVFile.ReadStream(file); } - protected abstract void ParseData(DataTable table); - - public TEntryType Lookup(String key) + public virtual TEntryType Lookup(TKeyType key) { var retVal = default(TEntryType); - if (_data.ContainsKey(key)) { - retVal = _data[key]; + if (Data.ContainsKey(key)) { + retVal = Data[key]; } return retVal; } diff --git a/VectoCore/Resources/Declaration/PT1.csv b/VectoCore/Resources/Declaration/PT1.csv new file mode 100644 index 0000000000000000000000000000000000000000..5339693866075e942899d3088ac851520a07edce --- /dev/null +++ b/VectoCore/Resources/Declaration/PT1.csv @@ -0,0 +1,11 @@ +rpm,PT1 +400,0 +800,0.47 +1000,0.58 +1200,0.53 +1400,0.46 +1500,0.43 +1750,0.22 +1800,0.2 +2000,0.11 +2500,0.11 diff --git a/VectoCore/VectoCore.csproj b/VectoCore/VectoCore.csproj index 57748b42c55c6fc162f56da22c5a1dba89a00ee7..ccfe6f136a87410320f27070e5b2d2ee6adc6570 100644 --- a/VectoCore/VectoCore.csproj +++ b/VectoCore/VectoCore.csproj @@ -229,6 +229,7 @@ <EmbeddedResource Include="Resources\Declaration\MissionCycles\MunicipalUtility.vdri" /> <EmbeddedResource Include="Resources\Declaration\MissionCycles\RegionalDelivery.vdri" /> <EmbeddedResource Include="Resources\Declaration\MissionCycles\UrbanDelivery.vdri" /> + <EmbeddedResource Include="Resources\Declaration\PT1.csv" /> </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <!-- To modify your build process, add your task inside one of the targets below and uncomment it. diff --git a/VectoCoreTest/Models/DeclarationDataTest.cs b/VectoCoreTest/Models/DeclarationDataTest.cs index 1247d546ec917088ed18bbe541c169bc82947dc5..88d29af67436638cd8fee703e54d3625517a0a9c 100644 --- a/VectoCoreTest/Models/DeclarationDataTest.cs +++ b/VectoCoreTest/Models/DeclarationDataTest.cs @@ -1,6 +1,8 @@ -using System.IO; +using System; +using System.IO; using System.Linq; using Microsoft.VisualStudio.TestTools.UnitTesting; +using TUGraz.VectoCore.Exceptions; using TUGraz.VectoCore.Models; using TUGraz.VectoCore.Models.Declaration; using TUGraz.VectoCore.Utils; @@ -38,40 +40,50 @@ namespace TUGraz.VectoCore.Tests.Models [TestMethod] public void PT1Test() { - //var pt1 = DeclarationData.PT1; - - //// FIXED POINTS - //Assert.AreEqual(0, pt1.Lookup(400)); - //Assert.AreEqual(0.47, pt1.Lookup(800)); - //Assert.AreEqual(0.58, pt1.Lookup(1000)); - //Assert.AreEqual(0.53, pt1.Lookup(1200)); - //Assert.AreEqual(0.46, pt1.Lookup(1400)); - //Assert.AreEqual(0.43, pt1.Lookup(1500)); - //Assert.AreEqual(0.22, pt1.Lookup(1750)); - //Assert.AreEqual(0.2, pt1.Lookup(1800)); - //Assert.AreEqual(0.11, pt1.Lookup(2000)); - //Assert.AreEqual(0.11, pt1.Lookup(2500)); - - //// INTERPOLATE - //Assert.AreEqual(0.235, pt1.Lookup(600)); - //Assert.AreEqual(0.525, pt1.Lookup(900)); - //Assert.AreEqual(0.555, pt1.Lookup(1100)); - //Assert.AreEqual(0.495, pt1.Lookup(1300)); - //Assert.AreEqual(0.445, pt1.Lookup(1450)); - //Assert.AreEqual(0.325, pt1.Lookup(1625)); - //Assert.AreEqual(0.21, pt1.Lookup(1775)); - //Assert.AreEqual(0.155, pt1.Lookup(1900)); - //Assert.AreEqual(0.11, pt1.Lookup(2250)); - - - // TODO EXTRAPOLATE - //Assert.AreEqual(??, pt1.Lookup(0)); - //Assert.AreEqual(??, pt1.Lookup(100)); - //Assert.AreEqual(??, pt1.Lookup(200)); - //Assert.AreEqual(??, pt1.Lookup(300)); - //Assert.AreEqual(??, pt1.Lookup(2500)); + const double TOLERANCE = 0.0001; + var pt1 = DeclarationData.PT1; + + // FIXED POINTS + Assert.AreEqual(0, pt1.Lookup(400.RPMtoRad()).Double(), TOLERANCE); + Assert.AreEqual(0.47, pt1.Lookup(800.RPMtoRad()).Double(), TOLERANCE); + Assert.AreEqual(0.58, pt1.Lookup(1000.RPMtoRad()).Double(), TOLERANCE); + Assert.AreEqual(0.53, pt1.Lookup(1200.RPMtoRad()).Double(), TOLERANCE); + Assert.AreEqual(0.46, pt1.Lookup(1400.RPMtoRad()).Double(), TOLERANCE); + Assert.AreEqual(0.43, pt1.Lookup(1500.RPMtoRad()).Double(), TOLERANCE); + Assert.AreEqual(0.22, pt1.Lookup(1750.RPMtoRad()).Double(), TOLERANCE); + Assert.AreEqual(0.2, pt1.Lookup(1800.RPMtoRad()).Double(), TOLERANCE); + Assert.AreEqual(0.11, pt1.Lookup(2000.RPMtoRad()).Double(), TOLERANCE); + Assert.AreEqual(0.11, pt1.Lookup(2500.RPMtoRad()).Double(), TOLERANCE); + + // INTERPOLATE + Assert.AreEqual(0.235, pt1.Lookup(600.RPMtoRad()).Double(), TOLERANCE); + Assert.AreEqual(0.525, pt1.Lookup(900.RPMtoRad()).Double(), TOLERANCE); + Assert.AreEqual(0.555, pt1.Lookup(1100.RPMtoRad()).Double(), TOLERANCE); + Assert.AreEqual(0.495, pt1.Lookup(1300.RPMtoRad()).Double(), TOLERANCE); + Assert.AreEqual(0.445, pt1.Lookup(1450.RPMtoRad()).Double(), TOLERANCE); + Assert.AreEqual(0.325, pt1.Lookup(1625.RPMtoRad()).Double(), TOLERANCE); + Assert.AreEqual(0.21, pt1.Lookup(1775.RPMtoRad()).Double(), TOLERANCE); + Assert.AreEqual(0.155, pt1.Lookup(1900.RPMtoRad()).Double(), TOLERANCE); + Assert.AreEqual(0.11, pt1.Lookup(2250.RPMtoRad()).Double(), TOLERANCE); + + + //TODO EXTRAPOLATE + Assert.AreEqual(0.11, pt1.Lookup(3000.RPMtoRad()).Double(), TOLERANCE); + AssertException<VectoException>(() => pt1.Lookup(200.RPMtoRad())); + AssertException<VectoException>(() => pt1.Lookup(0.RPMtoRad())); + } - Assert.Inconclusive(); + + public static void AssertException<T>(Action func, string message = null) where T : Exception + { + try { + func(); + Assert.Fail("Expected an exception."); + } catch (T ex) { + if (!string.IsNullOrEmpty(message)) { + Assert.AreEqual(message, ex.Message); + } + } } [TestMethod] diff --git a/VectoCoreTest/Models/SimulationComponentData/FullLoadCurveTest.cs b/VectoCoreTest/Models/SimulationComponentData/FullLoadCurveTest.cs index adb08905e87863379a57af9d11202a0c11e82e4f..7e66f3f63f80cd46db6a6cdb02101b793e7c3369 100644 --- a/VectoCoreTest/Models/SimulationComponentData/FullLoadCurveTest.cs +++ b/VectoCoreTest/Models/SimulationComponentData/FullLoadCurveTest.cs @@ -17,26 +17,26 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData { var fldCurve = FullLoadCurve.ReadFromFile(CoachEngineFLD); - Assert.AreEqual(1180, (double) fldCurve.FullLoadStationaryTorque(560.RPMtoRad()), Tolerance); - Assert.AreEqual(1352, (double) fldCurve.FullLoadStationaryTorque(2000.RPMtoRad()), Tolerance); - Assert.AreEqual(1231, (double) fldCurve.FullLoadStationaryTorque(580.RPMtoRad()), Tolerance); + Assert.AreEqual(1180, fldCurve.FullLoadStationaryTorque(560.RPMtoRad()).Double(), Tolerance); + Assert.AreEqual(1352, fldCurve.FullLoadStationaryTorque(2000.RPMtoRad()).Double(), Tolerance); + Assert.AreEqual(1231, fldCurve.FullLoadStationaryTorque(580.RPMtoRad()).Double(), Tolerance); } - [TestMethod] - public void TestFullLoadEngineSpeedRated() - { - var fldCurve = FullLoadCurve.ReadFromFile(CoachEngineFLD); - Assert.AreEqual(181.8444, (double)fldCurve.RatedSpeed(), Tolerance); - } + [TestMethod] + public void TestFullLoadEngineSpeedRated() + { + var fldCurve = FullLoadCurve.ReadFromFile(CoachEngineFLD); + Assert.AreEqual(181.8444, (double)fldCurve.RatedSpeed(), Tolerance); + } [TestMethod] public void TestFullLoadStaticPower() { var fldCurve = FullLoadCurve.ReadFromFile(CoachEngineFLD); - Assert.AreEqual(69198.814183, (double) fldCurve.FullLoadStationaryPower(560.RPMtoRad()), Tolerance); - Assert.AreEqual(283162.218372, (double) fldCurve.FullLoadStationaryPower(2000.RPMtoRad()), Tolerance); - Assert.AreEqual(74767.810760, (double) fldCurve.FullLoadStationaryPower(580.RPMtoRad()), Tolerance); + Assert.AreEqual(69198.814183, fldCurve.FullLoadStationaryPower(560.RPMtoRad()).Double(), Tolerance); + Assert.AreEqual(283162.218372, fldCurve.FullLoadStationaryPower(2000.RPMtoRad()).Double(), Tolerance); + Assert.AreEqual(74767.810760, fldCurve.FullLoadStationaryPower(580.RPMtoRad()).Double(), Tolerance); } [TestMethod] @@ -44,11 +44,11 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData { var fldCurve = FullLoadCurve.ReadFromFile(CoachEngineFLD); - Assert.AreEqual(-149, (double) fldCurve.DragLoadStationaryTorque(560.RPMtoRad()), Tolerance); - Assert.AreEqual(-301, (double) fldCurve.DragLoadStationaryTorque(2000.RPMtoRad()), Tolerance); - Assert.AreEqual(-148.5, (double) fldCurve.DragLoadStationaryTorque(580.RPMtoRad()), Tolerance); - Assert.AreEqual(-150, (double) fldCurve.DragLoadStationaryTorque(520.RPMtoRad()), Tolerance); - Assert.AreEqual(-339, (double) fldCurve.DragLoadStationaryTorque(2200.RPMtoRad()), Tolerance); + Assert.AreEqual(-149, fldCurve.DragLoadStationaryTorque(560.RPMtoRad()).Double(), Tolerance); + Assert.AreEqual(-301, fldCurve.DragLoadStationaryTorque(2000.RPMtoRad()).Double(), Tolerance); + Assert.AreEqual(-148.5, fldCurve.DragLoadStationaryTorque(580.RPMtoRad()).Double(), Tolerance); + Assert.AreEqual(-150, fldCurve.DragLoadStationaryTorque(520.RPMtoRad()).Double(), Tolerance); + Assert.AreEqual(-339, fldCurve.DragLoadStationaryTorque(2200.RPMtoRad()).Double(), Tolerance); } [TestMethod] @@ -56,9 +56,9 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData { var fldCurve = FullLoadCurve.ReadFromFile(CoachEngineFLD); - Assert.AreEqual(-8737.81636, (double) fldCurve.DragLoadStationaryPower(560.RPMtoRad()), Tolerance); - Assert.AreEqual(-63041.29254, (double) fldCurve.DragLoadStationaryPower(2000.RPMtoRad()), Tolerance); - Assert.AreEqual(-9019.51251, (double) fldCurve.DragLoadStationaryPower(580.RPMtoRad()), Tolerance); + Assert.AreEqual(-8737.81636, fldCurve.DragLoadStationaryPower(560.RPMtoRad()).Double(), Tolerance); + Assert.AreEqual(-63041.29254, fldCurve.DragLoadStationaryPower(2000.RPMtoRad()).Double(), Tolerance); + Assert.AreEqual(-9019.51251, fldCurve.DragLoadStationaryPower(580.RPMtoRad()).Double(), Tolerance); } [TestMethod] @@ -66,9 +66,9 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData { var fldCurve = FullLoadCurve.ReadFromFile(CoachEngineFLD); - Assert.AreEqual(0.6, (double) fldCurve.PT1(560.RPMtoRad()), Tolerance); - Assert.AreEqual(0.25, (double) fldCurve.PT1(2000.RPMtoRad()), Tolerance); - Assert.AreEqual(0.37, (double) fldCurve.PT1(1700.RPMtoRad()), Tolerance); + Assert.AreEqual(0.6, fldCurve.PT1(560.RPMtoRad()).Double(), Tolerance); + Assert.AreEqual(0.25, fldCurve.PT1(2000.RPMtoRad()).Double(), Tolerance); + Assert.AreEqual(0.37, fldCurve.PT1(1700.RPMtoRad()).Double(), Tolerance); } /// <summary> @@ -103,7 +103,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData { var curve = FullLoadCurve.ReadFromFile(@"TestData\Components\FullLoadCurve no header.vfld"); var result = curve.FullLoadStationaryTorque(1.SI<PerSecond>()); - Assert.AreNotEqual((double) result, 0.0); + Assert.AreNotEqual(result.Double(), 0.0); } /// <summary>