From 4592ca6d4e52318f1a0f735f18c3263bda344caa Mon Sep 17 00:00:00 2001 From: Michael Krisper <michael.krisper@tugraz.at> Date: Fri, 12 Aug 2022 16:32:50 +0200 Subject: [PATCH] Gear Disabling Features for Engineering and Declaration HeavyLorry, SingleBus --- .../InputData/DeclarationInputData.cs | 4 ++ .../AbstractSimulationDataAdapter.cs | 36 +++++++++++ .../DeclarationDataAdapterHeavyLorry.cs | 36 ++--------- .../DeclarationDataAdapterSingleBus.cs | 6 +- .../EngineeringDataAdapter.cs | 31 +++++---- .../Models/Simulation/Data/VectoRunData.cs | 12 ++-- .../Integration/TorqueLimitsTest.cs | 64 ++++++++++++++++++- 7 files changed, 135 insertions(+), 54 deletions(-) diff --git a/VectoCommon/VectoCommon/InputData/DeclarationInputData.cs b/VectoCommon/VectoCommon/InputData/DeclarationInputData.cs index 87eb17253b..04f8ae8fa3 100644 --- a/VectoCommon/VectoCommon/InputData/DeclarationInputData.cs +++ b/VectoCommon/VectoCommon/InputData/DeclarationInputData.cs @@ -124,6 +124,10 @@ namespace TUGraz.VectoCommon.InputData ///// </summary> //string Rim { get; } // deprecated + /// <summary> + /// P196, P197 TorqueLimits: Gear [-], MaxTorque [Nm] + /// cf. VECTO Input Parameters.xlsx + /// </summary> IList<ITorqueLimitInputData> TorqueLimits { get; } /// <summary> diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/AbstractSimulationDataAdapter.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/AbstractSimulationDataAdapter.cs index 126c19ea45..8a8d0f6f87 100644 --- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/AbstractSimulationDataAdapter.cs +++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/AbstractSimulationDataAdapter.cs @@ -37,6 +37,7 @@ using TUGraz.VectoCommon.InputData; using TUGraz.VectoCommon.Models; using TUGraz.VectoCommon.Utils; using TUGraz.VectoCore.InputData.Reader.ComponentData; +using TUGraz.VectoCore.Models.Declaration; using TUGraz.VectoCore.Models.SimulationComponent.Data; using TUGraz.VectoCore.Models.SimulationComponent.Data.ElectricMotor; using TUGraz.VectoCore.Models.SimulationComponent.Data.Engine; @@ -516,6 +517,41 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter return entries; } + + /// <summary> + /// Filters the gears based on disabling rule: Disable either the last 1 or 2 gears by setting their vehicle-level torque limit to 0. + /// </summary> + internal static IList<ITransmissionInputData> FilterDisabledGears(IList<ITorqueLimitInputData> torqueLimits, IGearboxDeclarationInputData gearboxData) { + if (torqueLimits == null || torqueLimits.Count == 0){ + return gearboxData?.Gears ?? new List<ITransmissionInputData>(); + } + + if (gearboxData == null) { + return new List<ITransmissionInputData>(); + } + + var gearsInput = gearboxData.Gears; + var lastGearNumber = gearsInput.Max(g => g.Gear); + var toRemove = torqueLimits + .Where(tqLimit => tqLimit.MaxTorque.IsEqual(0)) + .Select(tqLimit => gearsInput.FirstOrDefault(g => g.Gear == tqLimit.Gear)) + .Where(g => g != default) + .OrderBy(g => g.Gear) + .ToList(); + + if ((toRemove.Count == 1 && toRemove[0].Gear != lastGearNumber) + || (toRemove.Count == 2 && (toRemove[0].Gear != lastGearNumber-1 || toRemove[1].Gear != lastGearNumber)) + || toRemove.Count > 2) { + throw new VectoException("Only the last 1 or 2 gears can be disabled. Disabling gear {0} for a {1}-speed gearbox is not allowed.", + toRemove.Min(g => g.Gear), gearsInput.Count); + } + + foreach (var entry in toRemove) { + gearsInput.Remove(entry); + } + + return gearsInput; + } } } diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapterHeavyLorry.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapterHeavyLorry.cs index e092f19436..6a4723df7f 100644 --- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapterHeavyLorry.cs +++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapterHeavyLorry.cs @@ -238,12 +238,14 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter retVal.Inertia = DeclarationData.Engine.EngineInertia(retVal.Displacement, gearbox.Type); retVal.EngineStartTime = DeclarationData.Engine.DefaultEngineStartTime; + var limits = vehicle.TorqueLimits?.ToDictionary(e => e.Gear) ?? new Dictionary<int, ITorqueLimitInputData>(); - var numGears = gearbox.Gears.Count; + var gears = FilterDisabledGears(vehicle.TorqueLimits, gearbox); + var numGears = gears.Count; var fullLoadCurves = new Dictionary<uint, EngineFullLoadCurve>(numGears + 1); fullLoadCurves[0] = FullLoadCurveReader.Create(mode.FullLoadCurve, true); fullLoadCurves[0].EngineData = retVal; - foreach (var gear in gearbox.Gears) { + foreach (var gear in gears) { var maxTorque = VectoMath.Min( GbxMaxTorque(gear, numGears, fullLoadCurves[0].MaxTorque), VehMaxTorque(gear, numGears, limits, fullLoadCurves[0].MaxTorque)); @@ -356,7 +358,7 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter throw new VectoSimulationException("Unsupported gearbox type: {0}!", retVal.Type); } - var gearsInput = FilterDisabledGears(inputData, gearbox); + var gearsInput = FilterDisabledGears(inputData.TorqueLimits, gearbox); if (gearsInput.Count < 1) { throw new VectoSimulationException( @@ -431,34 +433,6 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter return retVal; } - /// <summary> - /// Filters the gears based on disabling rule: Disable either the last 1 or 2 gears by setting their vehicle-level torque limit to 0. - /// </summary> - private static IList<ITransmissionInputData> FilterDisabledGears(IVehicleDeclarationInputData inputData, IGearboxDeclarationInputData gearbox) - { - var gearsInput = gearbox.Gears; - var lastGearNumber = gearsInput.Max(g => g.Gear); - - if (inputData.TorqueLimits != null) { - var toRemove = inputData.TorqueLimits - .Where(tqLimit => tqLimit.Gear >= lastGearNumber - 1 && tqLimit.MaxTorque.IsEqual(0)) - .Select(tqLimit => gearsInput.FirstOrDefault(g => g.Gear == tqLimit.Gear)) - .Where(g => g != default) - .ToList(); - - if (toRemove.Count > 0 && toRemove.Min(g => g.Gear) <= gearsInput.Count - toRemove.Count) { - throw new VectoException("Only the last 1 or 2 gears can be disabled. Disabling gear {0} for a {1}-speed gearbox is not allowed.", - toRemove.Min(), gearsInput.Count); - } - - foreach (var entry in toRemove) { - gearsInput.Remove(entry); - } - } - - return gearsInput; - } - protected virtual TorqueConverterData CreateTorqueConverterData(GearboxType gearboxType, ITorqueConverterDeclarationInputData torqueConverter, double ratio, CombustionEngineData componentsEngineInputData) diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapterSingleBus.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapterSingleBus.cs index 5fd0766f12..1d41153479 100644 --- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapterSingleBus.cs +++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapterSingleBus.cs @@ -91,11 +91,13 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter retVal.Inertia = DeclarationData.Engine.EngineInertia(retVal.Displacement, gearbox.Type); retVal.EngineStartTime = DeclarationData.Engine.DefaultEngineStartTime; var limits = vehicle.TorqueLimits.ToDictionary(e => e.Gear); - var numGears = gearbox.Gears.Count; + var gears = FilterDisabledGears(vehicle.TorqueLimits, gearbox); + + var numGears = gears.Count; var fullLoadCurves = new Dictionary<uint, EngineFullLoadCurve>(numGears + 1); fullLoadCurves[0] = FullLoadCurveReader.Create(mode.FullLoadCurve, true); fullLoadCurves[0].EngineData = retVal; - foreach (var gear in gearbox.Gears) { + foreach (var gear in gears) { var maxTorque = VectoMath.Min( GbxMaxTorque(gear, numGears, fullLoadCurves[0].MaxTorque), VehMaxTorque(gear, numGears, limits, fullLoadCurves[0].MaxTorque)); diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/EngineeringDataAdapter.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/EngineeringDataAdapter.cs index cc5641aa7a..1b11643433 100644 --- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/EngineeringDataAdapter.cs +++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/EngineeringDataAdapter.cs @@ -188,7 +188,6 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter { var engine = vehicle.Components.EngineInputData; var gbx = vehicle.Components.GearboxInputData; - var torqueLimits = vehicle.TorqueLimits; var torqueConverter = vehicle.Components.TorqueConverterInputData; var tankSystem = vehicle.TankSystem; @@ -213,16 +212,15 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter ? (gbx.Type == GearboxType.APTN || gbx.Type == GearboxType.IHPC ? 0.SI<KilogramSquareMeter>() : torqueConverter.Inertia) : 0.SI<KilogramSquareMeter>()); retVal.EngineStartTime = engine.EngineStartTime ?? DeclarationData.Engine.DefaultEngineStartTime; - var limits = torqueLimits.ToDictionary(e => e.Gear); - var numGears = gbx?.Gears.Count ?? 0; - var fullLoadCurves = new Dictionary<uint, EngineFullLoadCurve>(numGears + 1); + var limits = vehicle.TorqueLimits.ToDictionary(e => e.Gear); + + var gears = FilterDisabledGears(vehicle.TorqueLimits, gbx); + var fullLoadCurves = new Dictionary<uint, EngineFullLoadCurve>(gears.Count + 1); fullLoadCurves[0] = FullLoadCurveReader.Create(engine.EngineModes.First().FullLoadCurve); fullLoadCurves[0].EngineData = retVal; - if (gbx != null) { - foreach (var gear in gbx.Gears) { - var maxTorque = VectoMath.Min(gear.MaxTorque, limits.GetVECTOValueOrDefault(gear.Gear)?.MaxTorque); - fullLoadCurves[(uint)gear.Gear] = IntersectFullLoadCurves(fullLoadCurves[0], maxTorque); - } + foreach (var gear in gears) { + var maxTorque = VectoMath.Min(gear.MaxTorque, limits.GetVECTOValueOrDefault(gear.Gear)?.MaxTorque); + fullLoadCurves[(uint)gear.Gear] = IntersectFullLoadCurves(fullLoadCurves[0], maxTorque); } retVal.FullLoadCurves = fullLoadCurves; @@ -326,17 +324,18 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter return retVal; } - //var gears = gearbox.Gears; if (gearbox.Gears.Count < 2) { throw new VectoSimulationException("At least two Gear-Entries must be defined in Gearbox!"); } + var gearsInput = FilterDisabledGears(inputData.JobInputData.Vehicle.TorqueLimits, gearbox); + SetEngineeringData(gearbox, gearshiftData, retVal); var hasTorqueConverter = retVal.Type.AutomaticTransmission() && retVal.Type != GearboxType.APTN && retVal.Type != GearboxType.IHPC; - var gearDifferenceRatio = hasTorqueConverter && gearbox.Gears.Count > 2 - ? gearbox.Gears[0].Ratio / gearbox.Gears[1].Ratio + var gearDifferenceRatio = hasTorqueConverter && gearsInput.Count > 2 + ? gearsInput[0].Ratio / gearsInput[1].Ratio : 1.0; var gears = new Dictionary<uint, GearData>(); @@ -346,8 +345,8 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter ? ShiftPolygonReader.Create(torqueConverter.ShiftPolygon) : DeclarationData.TorqueConverter.ComputeShiftPolygon(engineData.FullLoadCurves[0]); } - for (uint i = 0; i < gearbox.Gears.Count; i++) { - var gear = gearbox.Gears[(int)i]; + for (uint i = 0; i < gearsInput.Count; i++) { + var gear = gearsInput[(int)i]; var lossMap = CreateGearLossMap(gear, i, true, VehicleCategory.Unknown, gearbox.Type); ShiftPolygon shiftPolygon; @@ -355,11 +354,11 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter shiftPolygon = ShiftPolygonReader.Create(gear.ShiftPolygon); } else if (shiftPolygonCalc != null) { shiftPolygon = shiftPolygonCalc.ComputeDeclarationShiftPolygon(gearbox.Type, (int)i, - engineData?.FullLoadCurves[i + 1], gearbox.Gears, engineData, axlegearRatio, + engineData?.FullLoadCurves[i + 1], gearsInput, engineData, axlegearRatio, dynamicTyreRadius, runData.ElectricMachinesData?.FirstOrDefault()?.Item2); } else { shiftPolygon = DeclarationData.Gearbox.ComputeShiftPolygon(gearbox.Type, (int)i, - engineData?.FullLoadCurves[i + 1], gearbox.Gears, engineData, axlegearRatio, + engineData?.FullLoadCurves[i + 1], gearsInput, engineData, axlegearRatio, dynamicTyreRadius, runData.ElectricMachinesData?.FirstOrDefault()?.Item2); } diff --git a/VectoCore/VectoCore/Models/Simulation/Data/VectoRunData.cs b/VectoCore/VectoCore/Models/Simulation/Data/VectoRunData.cs index 9dcc8106ab..1a83b0cd01 100644 --- a/VectoCore/VectoCore/Models/Simulation/Data/VectoRunData.cs +++ b/VectoCore/VectoCore/Models/Simulation/Data/VectoRunData.cs @@ -42,6 +42,7 @@ using TUGraz.VectoCommon.Models; using TUGraz.VectoCommon.Utils; using TUGraz.VectoCore.Configuration; using TUGraz.VectoCore.InputData.Reader.ComponentData; +using TUGraz.VectoCore.InputData.Reader.DataObjectAdapter; using TUGraz.VectoCore.InputData.Reader.Impl; using TUGraz.VectoCore.Models.Declaration; using TUGraz.VectoCore.Models.SimulationComponent.Data; @@ -252,7 +253,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Data return ValidationResult.Success; } - private static ValidationResult CheckPowertrainLossMapsSizeConventionalPT(VectoRunData runData, GearboxData gearboxData, + private static ValidationResult CheckPowertrainLossMapsSizeConventionalPT(VectoRunData runData, GearboxData gearboxData, CombustionEngineData engineData) { @@ -270,14 +271,17 @@ namespace TUGraz.VectoCore.Models.Simulation.Data angledriveRatio * dynamicTyreRadius; var maxSpeed = VectoMath.Min(vehicleMaxSpeed, (runData.VehicleDesignSpeed ?? 90.KMPHtoMeterPerSecond()) + (runData.DriverData?.OverSpeed?.OverSpeed ?? 0.KMPHtoMeterPerSecond())); - if (gearboxData.Gears.Count + 1 != engineData.FullLoadCurves.Count) { + var gearsInput = AbstractSimulationDataAdapter.FilterDisabledGears(runData.VehicleData.InputData.TorqueLimits, gearboxData.InputData); + var gears = gearboxData.Gears.Where(f => gearsInput.Any(g => f.Key == g.Gear)).ToList(); + + if (gears.Count + 1 != engineData.FullLoadCurves.Count) { return new ValidationResult( $"number of full-load curves in engine does not match gear count. " + - $"engine fld: {engineData.FullLoadCurves.Count}, gears: {gearboxData.Gears.Count}"); + $"engine fld: {engineData.FullLoadCurves.Count}, gears: {gears.Count}"); } - foreach (var gear in gearboxData.Gears) { + foreach (var gear in gears) { var maxEngineSpeed = VectoMath.Min(engineData.FullLoadCurves[gear.Key].RatedSpeed, gear.Value.MaxSpeed); for (var angularVelocity = engineData.IdleSpeed; angularVelocity < maxEngineSpeed; diff --git a/VectoCore/VectoCoreTest/Integration/TorqueLimitsTest.cs b/VectoCore/VectoCoreTest/Integration/TorqueLimitsTest.cs index bc38385e9c..f9b7123116 100644 --- a/VectoCore/VectoCoreTest/Integration/TorqueLimitsTest.cs +++ b/VectoCore/VectoCoreTest/Integration/TorqueLimitsTest.cs @@ -35,6 +35,7 @@ using System.IO; using System.Linq; using Ninject; using NUnit.Framework; +using TUGraz.VectoCommon.Exceptions; using TUGraz.VectoCommon.Models; using TUGraz.VectoCommon.Utils; using TUGraz.VectoCore.InputData.FileIO.JSON; @@ -43,6 +44,7 @@ using TUGraz.VectoCore.Models.Simulation.Impl; using TUGraz.VectoCore.Models.Simulation.Impl.SimulatorFactory; using TUGraz.VectoCore.OutputData; using TUGraz.VectoCore.OutputData.FileIO; +using TUGraz.VectoCore.Tests.Utils; using Assert = NUnit.Framework.Assert; namespace TUGraz.VectoCore.Tests.Integration @@ -311,6 +313,66 @@ namespace TUGraz.VectoCore.Tests.Integration Assert.IsTrue(jobContainer.Runs.All(r => r.Success), string.Concat(jobContainer.Runs.Select(r => r.ExecException))); } - + [Category("LongRunning"), + TestCase(@"Testdata\Integration\DeclarationMode\Class2_RigidTruck_4x2_VehTorqueLimits\Class2_RigidTruck_vehTqLimit-disableGear6.vecto"), + TestCase(@"Testdata\Integration\DeclarationMode\Class2_RigidTruck_4x2_VehTorqueLimits\Class2_RigidTruck_vehTqLimit-disableGear6and5.vecto")] + public void TestRunDisableGearsWithTorqueLimitSimulations(string file) + { + var fileWriter = new FileOutputWriter(file); + var sumData = new SummaryDataContainer(fileWriter); + var inputDataProvider = JSONInputDataFactory.ReadJsonJob(file); + var factory = SimulatorFactory.CreateSimulatorFactory(ExecutionMode.Declaration, inputDataProvider, fileWriter); + var jobContainer = new JobContainer(sumData); + jobContainer.AddRuns(factory); + jobContainer.Execute(); + jobContainer.WaitFinished(); + Assert.IsTrue(jobContainer.Runs.All(r => r.Success), string.Concat(jobContainer.Runs.Select(r => r.ExecException))); + } + + [TestCase(@"Testdata\Integration\DeclarationMode\Class2_RigidTruck_4x2_VehTorqueLimits\Class2_RigidTruck_vehTqLimit-disableGear5invalid.vecto"), + TestCase(@"Testdata\Integration\DeclarationMode\Class2_RigidTruck_4x2_VehTorqueLimits\Class2_RigidTruck_vehTqLimit-disableGear4invalid.vecto"), + TestCase(@"Testdata\Integration\DeclarationMode\Class2_RigidTruck_4x2_VehTorqueLimits\Class2_RigidTruck_vehTqLimit-disableGear6and4invalid.vecto"), + TestCase(@"Testdata\Integration\DeclarationMode\Class2_RigidTruck_4x2_VehTorqueLimits\Class2_RigidTruck_vehTqLimit-disableGear1invalid.vecto")] + public void TestRunDisableGearsInvalid(string file) + { + var fileWriter = new FileOutputWriter(file); + var sumData = new SummaryDataContainer(fileWriter); + var inputDataProvider = JSONInputDataFactory.ReadJsonJob(file); + var factory = SimulatorFactory.CreateSimulatorFactory(ExecutionMode.Declaration, inputDataProvider, fileWriter); + var jobContainer = new JobContainer(sumData); + AssertHelper.Exception<VectoException>(() => jobContainer.AddRuns(factory), messageContains: "Only the last 1 or 2 gears can be disabled. Disabling gear "); + } + + [Category("LongRunning"), + TestCase(@"Testdata\Integration\EngineeringMode\Class2_RigidTruck_4x2_VehTorqueLimits\Class2_RigidTruck_vehTqLimit-disableGear6.vecto"), + TestCase(@"Testdata\Integration\EngineeringMode\Class2_RigidTruck_4x2_VehTorqueLimits\Class2_RigidTruck_vehTqLimit-disableGear6and5.vecto")] + public void TestRunDisableGearsWithTorqueLimitSimulationsEngineering(string file) + { + var fileWriter = new FileOutputWriter(file); + var sumData = new SummaryDataContainer(fileWriter); + var inputDataProvider = JSONInputDataFactory.ReadJsonJob(file); + var factory = SimulatorFactory.CreateSimulatorFactory(ExecutionMode.Engineering, inputDataProvider, fileWriter); + var jobContainer = new JobContainer(sumData); + jobContainer.AddRuns(factory); + jobContainer.Execute(); + jobContainer.WaitFinished(); + Assert.IsTrue(jobContainer.Runs.All(r => r.Success), string.Concat(jobContainer.Runs.Select(r => r.ExecException))); + } + + [TestCase(@"Testdata\Integration\EngineeringMode\Class2_RigidTruck_4x2_VehTorqueLimits\Class2_RigidTruck_vehTqLimit-disableGear5invalid.vecto"), + TestCase(@"Testdata\Integration\EngineeringMode\Class2_RigidTruck_4x2_VehTorqueLimits\Class2_RigidTruck_vehTqLimit-disableGear4invalid.vecto"), + TestCase(@"Testdata\Integration\EngineeringMode\Class2_RigidTruck_4x2_VehTorqueLimits\Class2_RigidTruck_vehTqLimit-disableGear6and4invalid.vecto"), + TestCase(@"Testdata\Integration\EngineeringMode\Class2_RigidTruck_4x2_VehTorqueLimits\Class2_RigidTruck_vehTqLimit-disableGear1invalid.vecto")] + public void TestRunDisableGearsInvalidEngineering(string file) + { + var fileWriter = new FileOutputWriter(file); + var sumData = new SummaryDataContainer(fileWriter); + var inputDataProvider = JSONInputDataFactory.ReadJsonJob(file); + var factory = SimulatorFactory.CreateSimulatorFactory(ExecutionMode.Engineering, inputDataProvider, fileWriter); + var jobContainer = new JobContainer(sumData); + AssertHelper.Exception<VectoException>(() => jobContainer.AddRuns(factory), messageContains: "Only the last 1 or 2 gears can be disabled. Disabling gear "); + } + + } } -- GitLab