diff --git a/VectoCore/VectoCore/InputData/Reader/ComponentData/TransmissionLossMapReader.cs b/VectoCore/VectoCore/InputData/Reader/ComponentData/TransmissionLossMapReader.cs index 36ce77fe11669efc652120b073633209bf85f9e8..52fe2f09a42a4e81beb88968e38b4a0648971619 100644 --- a/VectoCore/VectoCore/InputData/Reader/ComponentData/TransmissionLossMapReader.cs +++ b/VectoCore/VectoCore/InputData/Reader/ComponentData/TransmissionLossMapReader.cs @@ -59,8 +59,9 @@ namespace TUGraz.VectoCore.InputData.Reader.ComponentData /// <param name="data"></param> /// <param name="gearRatio"></param> /// <param name="gearName"></param> + /// <param name="extendLossMap"></param> /// <returns></returns> - public static TransmissionLossMap Create(DataTable data, double gearRatio, string gearName) + public static TransmissionLossMap Create(DataTable data, double gearRatio, string gearName, bool extendLossMap = false) { if (data == null || data.Columns.Count < 3) { throw new VectoException("TransmissionLossMap Data File for {0} must consist of 3 columns.", gearName); @@ -82,10 +83,59 @@ namespace TUGraz.VectoCore.InputData.Reader.ComponentData entries = CreateFromColumIndizes(data); } - + if (!extendLossMap) { + return new TransmissionLossMap(entries, gearRatio, gearName); + } + var orig = ""; + entries.ForEach(x =>orig +=string.Format("{0},{1},{2}" + Environment.NewLine, x.InputSpeed.AsRPM, x.InputTorque.Value(), x.TorqueLoss.Value())); + entries = ExtendLossMap(entries); + var extended = ""; + entries.ForEach(x => extended += string.Format("{0},{1},{2}" + Environment.NewLine, x.InputSpeed.AsRPM, x.InputTorque.Value(), x.TorqueLoss.Value())); return new TransmissionLossMap(entries, gearRatio, gearName); } + private static List<TransmissionLossMap.GearLossMapEntry> ExtendLossMap( + List<TransmissionLossMap.GearLossMapEntry> entries) + { + var maxRpm = entries.Max(x => x.InputSpeed); + var maxTorque = entries.Max(x => x.InputTorque); + var speedBuckets = new Dictionary<PerSecond, List<TransmissionLossMap.GearLossMapEntry>>() { + { 0.RPMtoRad(), new List<TransmissionLossMap.GearLossMapEntry>() }, + { 600.RPMtoRad(), new List<TransmissionLossMap.GearLossMapEntry>() }, + { 900.RPMtoRad(), new List<TransmissionLossMap.GearLossMapEntry>() }, + { 1200.RPMtoRad(), new List<TransmissionLossMap.GearLossMapEntry>() }, + { 1600.RPMtoRad(), new List<TransmissionLossMap.GearLossMapEntry>() }, + { 2000.RPMtoRad(), new List<TransmissionLossMap.GearLossMapEntry>() } + }; + for (var i = 2500; i < maxRpm.AsRPM; i += 500) { + speedBuckets.Add(i.RPMtoRad(), new List<TransmissionLossMap.GearLossMapEntry>()); + } + speedBuckets.Add(maxRpm, new List<TransmissionLossMap.GearLossMapEntry>()); + var keys = speedBuckets.Keys.ToArray(); + foreach (var entry in entries) { + foreach (var speed in keys) { + if (entry.InputTorque.IsGreaterOrEqual(0) && Math.Abs(speed.AsRPM - entry.InputSpeed.AsRPM) < 150) { + speedBuckets[speed].Add(entry); + } + } + } + var torqueStep = 500.SI<NewtonMeter>(); + foreach (var speedBucket in speedBuckets) { + if (speedBucket.Value.Count == 0) + continue; + double k, d, r; + VectoMath.LeastSquaresFitting(speedBucket.Value, x => x.InputTorque.Value(), x => x.TorqueLoss.Value(), out k, out d, + out r); + + for (var inTq = speedBucket.Value.Max(x => x.InputTorque) + torqueStep; inTq <= 2 * maxTorque; inTq += torqueStep) { + entries.Add(new TransmissionLossMap.GearLossMapEntry(speedBucket.Key, inTq, k * inTq + d.SI<NewtonMeter>())); + entries.Add(new TransmissionLossMap.GearLossMapEntry(speedBucket.Key, -inTq, k * inTq + d.SI<NewtonMeter>())); + } + } + + return entries; + } + /// <summary> /// Create a DataTable from an efficiency value. /// </summary> diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapter.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapter.cs index 41657c7df7cb3947029dcbc05d644b71076273ca..b0eae3f194b31f4bdd94ee3ed9032736bc51ea61 100644 --- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapter.cs +++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapter.cs @@ -247,7 +247,7 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter if (gear.LossMap == null) { throw new InvalidFileFormatException(string.Format("LossMap for Gear {0} is missing.", i + 1)); } - gearLossMap = TransmissionLossMapReader.Create(gear.LossMap, gear.Ratio, string.Format("Gear {0}", i + 1)); + gearLossMap = TransmissionLossMapReader.Create(gear.LossMap, gear.Ratio, string.Format("Gear {0}", i + 1), true); } catch (InvalidFileFormatException) { if (useEfficiencyFallback) { gearLossMap = TransmissionLossMapReader.Create(gear.Efficiency, gear.Ratio, string.Format("Gear {0}", i + 1)); diff --git a/VectoCore/VectoCoreTest/Models/SimulationComponent/GearboxTest.cs b/VectoCore/VectoCoreTest/Models/SimulationComponent/GearboxTest.cs index d902ff6958c158d4df595ef72a6d9b57d8d4e8a7..dc8277a9e0fc52db89b7bce5de6890f5015f7fc0 100644 --- a/VectoCore/VectoCoreTest/Models/SimulationComponent/GearboxTest.cs +++ b/VectoCore/VectoCoreTest/Models/SimulationComponent/GearboxTest.cs @@ -278,7 +278,8 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent public void Gearbox_LossMapExtrapolation_Declaration(string gbxFile, string engineFile, double ratio, double torque, double inAngularSpeed, double expectedTorque) { - var gearboxData = MockSimulationDataFactory.CreateGearboxDataFromFile(gbxFile, engineFile); + // read gearbox data in engineering mode so that the loss-map is not extrapolated. + var gearboxData = MockSimulationDataFactory.CreateGearboxDataFromFile(gbxFile, engineFile, false); var container = new VehicleContainer(ExecutionMode.Declaration); var runData = GetDummyRunData(gearboxData); var gearbox = new Gearbox(container, new AMTShiftStrategy(runData, container), runData); @@ -312,7 +313,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent public void Gearbox_LossMapExtrapolation_Engineering(string gbxFile, string engineFile, double ratio, double torque, double inAngularSpeed, double expectedTorque) { - var gearboxData = MockSimulationDataFactory.CreateGearboxDataFromFile(GearboxDataFile, EngineDataFile); + var gearboxData = MockSimulationDataFactory.CreateGearboxDataFromFile(GearboxDataFile, EngineDataFile, false); var container = new VehicleContainer(executionMode: ExecutionMode.Engineering); var runData = GetDummyRunData(gearboxData); var gearbox = new Gearbox(container, new AMTShiftStrategy(runData, container), runData); @@ -347,7 +348,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent public void Gearbox_LossMapExtrapolation_DryRun(string gbxFile, string engineFile, double ratio, double torque, double inAngularSpeed, bool extrapolated, double expectedTorque) { - var gearboxData = MockSimulationDataFactory.CreateGearboxDataFromFile(GearboxDataFile, EngineDataFile); + var gearboxData = MockSimulationDataFactory.CreateGearboxDataFromFile(GearboxDataFile, EngineDataFile, false); var container = new VehicleContainer(ExecutionMode.Engineering); var runData = GetDummyRunData(gearboxData); var gearbox = new Gearbox(container, new AMTShiftStrategy(runData, container), diff --git a/VectoCore/VectoCoreTest/Models/SimulationComponentData/GearboxDataTest.cs b/VectoCore/VectoCoreTest/Models/SimulationComponentData/GearboxDataTest.cs index 25e65c5ef2001396fc2537f188d3224466506cb3..57eaeb48bf8c29c409289159b4d03ab132a43e01 100644 --- a/VectoCore/VectoCoreTest/Models/SimulationComponentData/GearboxDataTest.cs +++ b/VectoCore/VectoCoreTest/Models/SimulationComponentData/GearboxDataTest.cs @@ -333,5 +333,31 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData var maxTorque = gbxFld.FullLoadStationaryTorque(800.RPMtoRad()); Assert.AreEqual(750, maxTorque.Value()); } + + [TestCase()] + public void TestLossMapExtension() + { + var gbxFile = @"TestData\Components\24t Coach.vgbx"; + var engineFile = @"TestData\Components\24t Coach.veng"; + + var gearboxDataOrig = MockSimulationDataFactory.CreateGearboxDataFromFile(gbxFile, engineFile, false); + // read loss-map in declaration mode to extrapolate on reading. + var gearboxDataExt = MockSimulationDataFactory.CreateGearboxDataFromFile(gbxFile, engineFile, true); + + var rpm = 100.RPMtoRad(); + var tq = -3000.SI<NewtonMeter>(); + var lookupOrig = gearboxDataOrig.Gears[7].LossMap.GetTorqueLoss(rpm, tq); + var lookupExt = gearboxDataExt.Gears[7].LossMap.GetTorqueLoss(rpm, tq); + + Assert.IsTrue(lookupOrig.Extrapolated); + Assert.IsFalse(lookupExt.Extrapolated); + + rpm = 1200.RPMtoRad(); + lookupOrig = gearboxDataOrig.Gears[7].LossMap.GetTorqueLoss(rpm, tq); + lookupExt = gearboxDataExt.Gears[7].LossMap.GetTorqueLoss(rpm, tq); + + Assert.IsTrue(lookupOrig.Extrapolated); + Assert.IsFalse(lookupExt.Extrapolated); + } } } \ No newline at end of file