From e1653303df3366b6dfb2138b0cd9e5633a3c844d Mon Sep 17 00:00:00 2001 From: "VKMTHD\\haraldmartini" <martini@ivt.tugraz.at> Date: Tue, 11 Mar 2025 14:53:24 +0100 Subject: [PATCH 01/22] Remamed AMTShiftStrategyTests.cs --- .../{AMTShistStrategyTests.cs => AMTShiftStrategyTests.cs} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/{AMTShistStrategyTests.cs => AMTShiftStrategyTests.cs} (99%) diff --git a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/AMTShistStrategyTests.cs b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/AMTShiftStrategyTests.cs similarity index 99% rename from Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/AMTShistStrategyTests.cs rename to Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/AMTShiftStrategyTests.cs index 2210187284..f522c312af 100644 --- a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/AMTShistStrategyTests.cs +++ b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/AMTShiftStrategyTests.cs @@ -22,7 +22,7 @@ using Assert = NUnit.Framework.Assert; namespace TUGraz.Vecto.UnitTests.TestCases.Components.GearShiftStrategy; -public class AMTShistStrategyTests +public class AMTShiftStrategyTests { [TestCase(8, 7, 1800, 750, true), TestCase(7, 6, 1800, 750, true), -- GitLab From a5028da618c02a8c207f77cf059f2bb079f7f093 Mon Sep 17 00:00:00 2001 From: "VKMTHD\\haraldmartini" <martini@ivt.tugraz.at> Date: Tue, 11 Mar 2025 15:13:31 +0100 Subject: [PATCH 02/22] Added Tests to AMTShiftStrategyTests.cs --- .../AMTShiftStrategyTests.cs | 200 ++++++++++++++++++ 1 file changed, 200 insertions(+) diff --git a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/AMTShiftStrategyTests.cs b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/AMTShiftStrategyTests.cs index f522c312af..13d05f4e4a 100644 --- a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/AMTShiftStrategyTests.cs +++ b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/AMTShiftStrategyTests.cs @@ -14,6 +14,7 @@ using TUGraz.VectoCore.Models.SimulationComponent; using TUGraz.VectoCore.Models.SimulationComponent.Data; using TUGraz.VectoCore.Models.SimulationComponent.Data.Engine; using TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox; +// using TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox; using TUGraz.VectoCore.Models.SimulationComponent.Impl; using TUGraz.VectoCore.Models.SimulationComponent.Impl.Gearbox; using TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies; @@ -108,6 +109,205 @@ TestCase(8, 4, 15000, 200, true),] var absTime = 0.SI<Second>(); var dt = 2.SI<Second>(); + var expectedN = n.RPMtoRad(); + var angularVelocity = expectedN / ratios[gear]; + + var gearShiftPosition = shiftStrategy.InitGear(0.SI<Second>(), Constants.SimulationSettings.TargetTimeInterval, 1.SI<NewtonMeter>(), + angularVelocity); + + absTime += dt; + + var expectedT = tq.SI<NewtonMeter>(); + var torque = expectedT * ratios[gear]; + + + var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, torque, angularVelocity, expectedT, expectedN, + new GearshiftPosition((uint)gear), -double.MaxValue.SI<Second>(), new ResponseSuccess(this)); + + Assert.AreEqual(shiftExpected, shiftRequired); + Assert.AreEqual(newGear, shiftStrategy.NextGear.Gear); + } + + + [TestCase(2, 3, 800, 1400, 20_000, true, Description = "A gear would be skipped, but due to the uphill driving conditions, the next gear should be used")] + [TestCase(3, 3, 1000, 1400, 30_000, false, Description = "No upshifting because acceleration would be to low")] + public void Gearbox_ShiftUpUphill(int gear, int newGear, double tq, double n, double slopeResistance, bool shiftExpected) + { + // the first element 0.0 is just a placeholder for axlegear, not used in this test + var ratios = new[] { 0.0, 6.38, 4.63, 3.44, 2.59, 1.86, 1.35, 1, 0.76 }; + var runData = GetRunData(ratios); + + var container = GetMockVehicleContainer(runData); + + var accEstimationLookAhead = Constants.SimulationSettings.GearboxLookaheadForAccelerationEstimation; + + container.Setup(c => c.VehicleInfo.SlopeResistance(It.IsAny<Radian>())).Returns(slopeResistance.SI<Newton>()); + + + //container.Setup(c => c.DrivingCycleInfo.CycleLookAhead(accEstimationLookAhead)) + // .Returns(new DrivingCycleData.DrivingCycleEntry() { + // Altitude = 100.SI<Meter>() + // }); + //container.Setup(c => c.DrivingCycleInfo.Altitude).Returns(0.SI<Meter>()); + + + + + + + var testPt = GetMockTestPowertrain(runData); + + var ptBuilder = new Mock<ISimplePowertrainBuilder>(); + ptBuilder.Setup(p => p.CreateTestPowertrain(It.IsAny<IVehicleContainer>(), It.IsAny<bool>(), It.IsAny<VectoSimulationJobType?>())) + .Returns(testPt.Object); + container.Setup(c => c.SimplePowertrainBuilder).Returns(ptBuilder.Object); + + var gbx = GetMockGearbox(container); + Mock.Get(container.Object.EngineInfo).Setup(e => e.EngineSpeed).Returns(() => n.RPMtoRad()); + Mock.Get(container.Object.EngineInfo).Setup(e => e.EngineN95hSpeed).Returns(2000.RPMtoRad()); + + var shiftStrategy = new AMTShiftStrategy(container.Object); + shiftStrategy.Gearbox = gbx.Object; + + var absTime = 0.SI<Second>(); + var dt = 2.SI<Second>(); + + var expectedN = n.RPMtoRad(); + var angularVelocity = expectedN / ratios[gear]; + + var gearShiftPosition = shiftStrategy.InitGear(0.SI<Second>(), Constants.SimulationSettings.TargetTimeInterval, 1.SI<NewtonMeter>(), + angularVelocity); + + absTime += dt; + + var expectedT = tq.SI<NewtonMeter>(); + var torque = expectedT * ratios[gear]; + + + var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, torque, angularVelocity, expectedT, expectedN, + new GearshiftPosition((uint)gear), -double.MaxValue.SI<Second>(), new ResponseSuccess(this)); + + Assert.AreEqual(shiftExpected, shiftRequired); + Assert.AreEqual(newGear, shiftStrategy.NextGear.Gear); + } + + + + [TestCase(7, 1, 1000, 1400, true)] + [TestCase(7, 2, 400, 200, true)] + public void InitStartGear(int gear, int newGear, double tq, double n, bool shiftExpected) + { + // the first element 0.0 is just a placeholder for axlegear, not used in this test + var ratios = new[] { 0.0, 6.38, 5.2, 4.3, 3.2, 2.5, 1.8, 1, 0.76 }; + var runData = GetRunData(ratios); + + var container = GetMockVehicleContainer(runData); + container.Setup(c => c.VehicleInfo.VehicleSpeed).Returns(0.KMPHtoMeterPerSecond()); + var testPt = GetMockTestPowertrain(runData); + + var ptBuilder = new Mock<ISimplePowertrainBuilder>(); + ptBuilder.Setup(p => p.CreateTestPowertrain(It.IsAny<IVehicleContainer>(), It.IsAny<bool>(), It.IsAny<VectoSimulationJobType?>())) + .Returns(testPt.Object); + container.Setup(c => c.SimplePowertrainBuilder).Returns(ptBuilder.Object); + + var gbx = GetMockGearbox(container); + Mock.Get(container.Object.EngineInfo).Setup(e => e.EngineSpeed).Returns(() => n.RPMtoRad()); + Mock.Get(container.Object.EngineInfo).Setup(e => e.EngineN95hSpeed).Returns(2000.RPMtoRad()); + + var shiftStrategy = new AMTShiftStrategy(container.Object); + shiftStrategy.Gearbox = gbx.Object; + + var absTime = 0.SI<Second>(); + var dt = 2.SI<Second>(); + + var expectedN = n.RPMtoRad(); + var angularVelocity = expectedN / ratios[gear]; + + + testPt.Setup(t => t.Gearbox.Request( + It.IsAny<Second>(), + It.IsAny<Second>(), + It.IsAny<NewtonMeter>(), + It.IsAny<PerSecond>(), + true)).Returns(new ResponseDryRun(null) + { + Engine = { + TotalTorqueDemand = 2.SI<NewtonMeter>(), + DynamicFullLoadTorque = 4.SI<NewtonMeter>(), + EngineSpeed = 600.RPMtoRad(), + } + }); + + var gearShiftPosition = shiftStrategy.InitGear(0.SI<Second>(), Constants.SimulationSettings.TargetTimeInterval, 1.SI<NewtonMeter>(), + angularVelocity); + + absTime += dt; + + var expectedT = tq.SI<NewtonMeter>(); + var torque = expectedT * ratios[gear]; + + + //var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, torque, angularVelocity, expectedT, expectedN, + // new GearshiftPosition((uint)gear), -double.MaxValue.SI<Second>(), new ResponseSuccess(this)); + + //Assert.AreEqual(shiftExpected, shiftRequired); + Assert.GreaterOrEqual(shiftStrategy.MaxStartGear.Gear, newGear); + Assert.AreEqual(newGear, shiftStrategy.NextGear.Gear); + } + + + [TestCase(2, 1, 2, 1000, 300)] + [TestCase(3, 2, 2, 1000, 1400)] + [TestCase(8, 7, 2, 1800, 750)] + [TestCase(7, 6, 2, 1800, 750)] + [TestCase(6, 5, 2, 1800, 750)] + [TestCase(5, 4, 2, 1800, 750)] + [TestCase(4, 3, 2, 1800, 750)] + [TestCase(3, 2, 2, 1800, 750)] + [TestCase(2, 2, 2, 1900, 750)] + [TestCase(1, 2, 2, 1200, 700)] + [TestCase(8, 4, 2, 15000, 200)] + [TestCase(2, 2, 2, 300, 1000)] + public void Gearbox_PTO(int gear, int newGear, int ptoGear, double tq, double n) + { + var shiftExpected = gear != newGear; + // the first element 0.0 is just a placeholder for axlegear, not used in this test + var ratios = new[] { 0.0, 6.38, 4.63, 3.44, 2.59, 1.86, 1.35, 1, 0.76 }; + var runData = GetRunData(ratios); + + runData.DriverData = new DriverData() { + PTODriveRoadsweepingGear = new GearshiftPosition((uint)ptoGear) + }; + + var container = GetMockVehicleContainer(runData); + + container.Setup(c => c.DrivingCycleInfo.CycleData).Returns( + new CycleData() { + LeftSample = new DrivingCycleData.DrivingCycleEntry() { + PTOActive = PTOActivity.PTOActivityRoadSweeping, + RoadGradient = 0.SI<Radian>(), + } + } + ); + + + var testPt = GetMockTestPowertrain(runData); + + var ptBuilder = new Mock<ISimplePowertrainBuilder>(); + ptBuilder.Setup(p => p.CreateTestPowertrain(It.IsAny<IVehicleContainer>(), It.IsAny<bool>(), It.IsAny<VectoSimulationJobType?>())) + .Returns(testPt.Object); + container.Setup(c => c.SimplePowertrainBuilder).Returns(ptBuilder.Object); + + var gbx = GetMockGearbox(container); + Mock.Get(container.Object.EngineInfo).Setup(e => e.EngineSpeed).Returns(() => n.RPMtoRad()); + Mock.Get(container.Object.EngineInfo).Setup(e => e.EngineN95hSpeed).Returns(2000.RPMtoRad()); + + var shiftStrategy = new AMTShiftStrategy(container.Object); + shiftStrategy.Gearbox = gbx.Object; + + var absTime = 0.SI<Second>(); + var dt = 2.SI<Second>(); + var expectedN = n.RPMtoRad(); var angularVelocity = expectedN / ratios[gear]; -- GitLab From 1be37e9d68bd550a19090cb2ad804c7b1841b5ca Mon Sep 17 00:00:00 2001 From: "VKMTHD\\haraldmartini" <martini@ivt.tugraz.at> Date: Thu, 13 Mar 2025 10:49:43 +0100 Subject: [PATCH 03/22] Simple Powertrain Builder use overloads instead of default parameters (they dont go well with mocking) --- .../Models/Simulation/ISimplePowertrainBuilder.cs | 5 ++--- .../Models/Simulation/Impl/SimplePowertrainBuilder.cs | 8 +++++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/VectoCore/VectoCore/Models/Simulation/ISimplePowertrainBuilder.cs b/VectoCore/VectoCore/Models/Simulation/ISimplePowertrainBuilder.cs index b46bbb0b01..a2146fe114 100644 --- a/VectoCore/VectoCore/Models/Simulation/ISimplePowertrainBuilder.cs +++ b/VectoCore/VectoCore/Models/Simulation/ISimplePowertrainBuilder.cs @@ -9,9 +9,8 @@ namespace TUGraz.VectoCore.Models.Simulation public interface ISimplePowertrainBuilder { //ITestPowertrain CreateTestPowertrain(ISimpleVehicleContainer testContainer, IDataBus realContainer, bool createDriver); - - ITestPowertrain CreateTestPowertrain(IVehicleContainer realContainer, bool createDriver, VectoSimulationJobType? overrideJobType = null); - + ITestPowertrain CreateTestPowertrain(IVehicleContainer realContainer, bool createDriver, VectoSimulationJobType overrideJobType); + ITestPowertrain CreateTestPowertrain(IVehicleContainer realContainer, bool createDriver); ITestGenset CreateTestGenset(IVehicleContainer realContainer); /// <summary> diff --git a/VectoCore/VectoCore/Models/Simulation/Impl/SimplePowertrainBuilder.cs b/VectoCore/VectoCore/Models/Simulation/Impl/SimplePowertrainBuilder.cs index 9068c164fe..2ce2331314 100644 --- a/VectoCore/VectoCore/Models/Simulation/Impl/SimplePowertrainBuilder.cs +++ b/VectoCore/VectoCore/Models/Simulation/Impl/SimplePowertrainBuilder.cs @@ -32,12 +32,18 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl } - public ITestPowertrain CreateTestPowertrain(IVehicleContainer realContainer, bool createDriver, VectoSimulationJobType? overrideJobType) + public ITestPowertrain CreateTestPowertrain(IVehicleContainer realContainer, bool createDriver, VectoSimulationJobType overrideJobType) { var testContainer = BuildSimplePowertrain(realContainer.RunData, overrideJobType); return new TestPowertrain(testContainer, realContainer, createDriver); } + public ITestPowertrain CreateTestPowertrain(IVehicleContainer realContainer, bool createDriver) + { + var testContainer = BuildSimplePowertrain(realContainer.RunData, null); + return new TestPowertrain(testContainer, realContainer, createDriver); + } + public ITestGenset CreateTestGenset(IVehicleContainer realContainer) { var testContainer = BuildSimpleGenSet(realContainer.RunData); -- GitLab From 2e8150be4ae482ec9eeeb7ce2658d927cd4d72ef Mon Sep 17 00:00:00 2001 From: "VKMTHD\\haraldmartini" <martini@ivt.tugraz.at> Date: Thu, 13 Mar 2025 10:50:29 +0100 Subject: [PATCH 04/22] Added AMTShiftStrategyOptimizedTests.cs (with mocked gearboxes) --- .../AMTShiftStrategyOptimizedTests.cs | 1105 +++++++++++++++++ 1 file changed, 1105 insertions(+) create mode 100644 Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/AMTShiftStrategyOptimizedTests.cs diff --git a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/AMTShiftStrategyOptimizedTests.cs b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/AMTShiftStrategyOptimizedTests.cs new file mode 100644 index 0000000000..5e72e31099 --- /dev/null +++ b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/AMTShiftStrategyOptimizedTests.cs @@ -0,0 +1,1105 @@ +using System.ComponentModel.Design.Serialization; +using Moq; +using NUnit.Framework; +using TUGraz.VectoCommon.InputData; +using TUGraz.VectoCommon.Models; +using TUGraz.VectoCommon.Utils; +using TUGraz.VectoCore.Configuration; +using TUGraz.VectoCore.InputData.Reader.ComponentData; +using TUGraz.VectoCore.Models.Connector.Ports; +using TUGraz.VectoCore.Models.Connector.Ports.Impl; +using TUGraz.VectoCore.Models.Declaration; +using TUGraz.VectoCore.Models.Simulation; +using TUGraz.VectoCore.Models.Simulation.Data; +using TUGraz.VectoCore.Models.Simulation.DataBus; +using TUGraz.VectoCore.Models.Simulation.Impl; +using TUGraz.VectoCore.Models.SimulationComponent; +using TUGraz.VectoCore.Models.SimulationComponent.Data; +using TUGraz.VectoCore.Models.SimulationComponent.Data.Engine; +using TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox; +using TUGraz.VectoCore.Models.SimulationComponent.Impl; +using TUGraz.VectoCore.Models.SimulationComponent.Impl.Gearbox; +using TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies; +using TUGraz.VectoCore.Tests.Utils; +using Assert = NUnit.Framework.Assert; +using Range = System.Range; + +namespace TUGraz.Vecto.UnitTests.TestCases.Components.GearShiftStrategy; + +[TestFixture] +public class AMTShiftStrategyOptimizedTests +{ + [TestCase(8, 7, 1800, 750, true), +TestCase(7, 6, 1800, 750, true), +TestCase(6, 5, 1800, 750, true), +TestCase(5, 4, 1800, 750, true), +TestCase(4, 3, 1800, 750, true), +TestCase(3, 2, 1800, 750, true), +TestCase(2, 1, 1900, 750, true), +TestCase(1, 1, 1200, 700, false), +TestCase(8, 4, 15000, 200, true),] + public void Gearbox_ShiftDown_ACEA_Shiftlines(int gear, int newGear, double t, double n, bool shiftExpected) + { + // the first element 0.0 is just a placeholder for axlegear, not used in this test + var ratios = new[] { 0.0, 6.38, 4.63, 3.44, 2.59, 1.86, 1.35, 1, 0.76 }; + + //Get Containers and MockData + var vehicleContainer = GetMocks(ratios, out var runData, out var testPowertrain); + + + var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); + vehicleContainer.Setup(c => c.EngineInfo.EngineSpeed).Returns(() => n.RPMtoRad()); + vehicleContainer.Setup(c => c.EngineInfo.EngineN95hSpeed).Returns(() => 2000.RPMtoRad()); + + + var absTime = 0.SI<Second>(); + var dt = 2.SI<Second>(); + + var expectedN = n.RPMtoRad(); + var angularVelocity = expectedN / ratios[gear]; + + + var gearShiftPosition = shiftStrategy.InitGear(0.SI<Second>(), Constants.SimulationSettings.TargetTimeInterval, 1.SI<NewtonMeter>(), + angularVelocity); + + var expectedT = t.SI<NewtonMeter>(); + var torque = expectedT * ratios[gear]; + + var response = new ResponseSuccess(this); + response.Engine.TorqueOutDemand = expectedT; + response.Engine.EngineSpeed = expectedN; + + var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, torque, angularVelocity, expectedT, expectedN, + new GearshiftPosition((uint)gear), -double.MaxValue.SI<Second>(), response); + Assert.AreEqual(shiftExpected, shiftRequired); + Assert.AreEqual(newGear, shiftStrategy.NextGear.Gear); + } + + + [TestCase(7, 8, 1000, 1400, true), + TestCase(6, 8, 800, 1400, true), + TestCase(5, 6, 1000, 1400, true), + TestCase(4, 5, 1000, 1400, true), + TestCase(3, 4, 1000, 1400, true), + TestCase(2, 4, 800, 1400, true), + TestCase(1, 2, 1000, 1400, true), + TestCase(8, 8, 1000, 1400, false), + TestCase(1, 6, 200, 9000, true),] + public void Gearbox_ShiftUp(int gear, int newGear, double tq, double n, bool shiftExpected) + { + // the first element 0.0 is just a placeholder for axlegear, not used in this test + var ratios = new[] { 0.0, 6.38, 4.63, 3.44, 2.59, 1.86, 1.35, 1, 0.76 }; + + + var container = GetMocks(ratios, out var runData, out _); + var shiftStrategy = GetShiftStrategyAndGearbox(container, out var gbx); + + container.Setup(c => c.EngineInfo.EngineSpeed).Returns(() => n.RPMtoRad()); + container.Setup(c => c.EngineInfo.EngineN95hSpeed).Returns(2000.RPMtoRad()); + + + var absTime = 0.SI<Second>(); + var dt = 2.SI<Second>(); + + var expectedN = n.RPMtoRad(); + var angularVelocity = expectedN / ratios[gear]; + + var gearShiftPosition = shiftStrategy.InitGear(0.SI<Second>(), Constants.SimulationSettings.TargetTimeInterval, 1.SI<NewtonMeter>(), + angularVelocity); + + absTime += dt; + + var expectedT = tq.SI<NewtonMeter>(); + var torque = expectedT * ratios[gear]; + + var response = new ResponseSuccess(this); + //Setup Response + response.Engine.TorqueOutDemand = expectedT; + response.Engine.EngineSpeed = expectedN; + + + var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, torque, angularVelocity, expectedT, expectedN, + new GearshiftPosition((uint)gear), -double.MaxValue.SI<Second>(), response); + + + + Assert.AreEqual(shiftExpected, shiftRequired); + Assert.AreEqual(newGear, shiftStrategy.NextGear.Gear); + } + + + // [TestCase(2, 3, 800, 1400, 20_000, true, Description = "A gear would be skipped, but due to the uphill driving conditions, the next gear should be used")] + // [TestCase(3, 3, 1000, 1400, 30_000, false, Description = "No upshifting because acceleration would be to low")] + // public void Gearbox_ShiftUpUphill(int gear, int newGear, double tq, double n, double slopeResistance, bool shiftExpected) + // { + // // the first element 0.0 is just a placeholder for axlegear, not used in this test + // var ratios = new[] { 0.0, 6.38, 4.63, 3.44, 2.59, 1.86, 1.35, 1, 0.76 }; + // var container = GetMocks(ratios, out var runData, out _); + // + // var accEstimationLookAhead = Constants.SimulationSettings.GearboxLookaheadForAccelerationEstimation; + // + // container.Setup(c => c.VehicleInfo.SlopeResistance(It.IsAny<Radian>())).Returns(slopeResistance.SI<Newton>()); + // container.Setup(c => c.DrivingCycleInfo.CycleLookAhead(accEstimationLookAhead)) + // .Returns(new DrivingCycleData.DrivingCycleEntry() { + // Altitude = 100.SI<Meter>() + // }); + // container.Setup(c => c.DrivingCycleInfo.Altitude).Returns(0.SI<Meter>()); + // + // + // + // + // + // + // // var testPt = GetMockTestPowertrain(runData, out var simplePt); + // // + // // var ptBuilder = new Mock<ISimplePowertrainBuilder>(); + // // ptBuilder.Setup(p => p.CreateTestPowertrain<Gearbox>(It.IsAny<ISimpleVehicleContainer>(), It.IsAny<IDataBus>())) + // // .Returns(testPt.Object); + // // + // // ptBuilder.Setup(p => p.BuildSimplePowertrain(It.IsAny<VectoRunData>())).Returns(simplePt.Object); + // // container.Setup(c => c.SimplePowertrainBuilder).Returns(ptBuilder.Object); + // // + // // var gbx = GetMockGearbox(container); + // // Mock.Get(container.Object.EngineInfo).Setup(e => e.EngineSpeed).Returns(() => n.RPMtoRad()); + // // Mock.Get(container.Object.EngineInfo).Setup(e => e.EngineN95hSpeed).Returns(2000.RPMtoRad()); + // + // var shiftStrategy = GetShiftStrategyAndGearbox(container, out var gbx); + // // var shiftStrategy = new AMTShiftStrategyOptimized(container.Object); + // // shiftStrategy.Gearbox = gbx.Object; + // + // var absTime = 0.SI<Second>(); + // var dt = 2.SI<Second>(); + // + // var expectedN = n.RPMtoRad(); + // var angularVelocity = expectedN / ratios[gear]; + // + // var gearShiftPosition = shiftStrategy.InitGear(0.SI<Second>(), Constants.SimulationSettings.TargetTimeInterval, 1.SI<NewtonMeter>(), + // angularVelocity); + // + // absTime += dt; + // + // var expectedT = tq.SI<NewtonMeter>(); + // var torque = expectedT * ratios[gear]; + // + // + // var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, torque, angularVelocity, expectedT, expectedN, + // new GearshiftPosition((uint)gear), -double.MaxValue.SI<Second>(), new ResponseSuccess(this)); + // + // Assert.AreEqual(shiftExpected, shiftRequired); + // Assert.AreEqual(newGear, shiftStrategy.NextGear.Gear); + // } + // + // + [TestCase] + public void GetMocksTest() + { + // the first element 0.0 is just a placeholder for axlegear, not used in this test + var ratios = new[] { 0.0, 6.38, 4.63, 3.84, 2.59, 1.86, 1.35, 1, 0.76 }; + + var mockContainer = GetMocks(ratios, + out var runData, + out var testPowertrain); + + var container = mockContainer.Object; + var createdTestPowertrain = container.SimplePowertrainBuilder.CreateTestPowertrain(container, false); + + Assert.NotNull(createdTestPowertrain.Container.GearboxOutPort); + Assert.NotNull(createdTestPowertrain); + } + + + [TestCase(1, 2, 100, 900, true)] + [TestCase(4, 5, 100, 900, true)] + [TestCase(5, 6, 100, 900, true)] + + public void Gearbox_EarlyUpShift(int gear, int newGear, double tq, double n, bool shiftExpected) + { + // the first element 0.0 is just a placeholder for axlegear, not used in this test + var ratios = new[] { 0.0, 6.38, 4.63, 3.84, 2.59, 1.86, 1.35, 1, 0.76 }; + + var container = GetMocks(ratios, + out var runData, + out var testPowertrain); + + + + + runData.GearshiftParameters.RatioEarlyUpshiftFC = 10; + runData.GearshiftParameters.MinEngineSpeedPostUpshift = 1.RPMtoRad(); + runData.GearshiftParameters.TorqueReserve = 0.1; + runData.GearshiftParameters.RatingFactorCurrentGear = 0.97; + var shiftStrategy = GetShiftStrategyAndGearbox(container, out var gbx); + + + container.Setup(c => c.EngineInfo.EngineSpeed).Returns(() => n.RPMtoRad()); + container.Setup(c => c.EngineInfo.EngineN95hSpeed).Returns(() => 2000.RPMtoRad()); + + + var absTime = 0.SI<Second>(); + var dt = 2.SI<Second>(); + + var expectedN = n.RPMtoRad(); + var angularVelocity = expectedN / ratios[gear]; + + var gearShiftPosition = shiftStrategy.InitGear(0.SI<Second>(), Constants.SimulationSettings.TargetTimeInterval, 1.SI<NewtonMeter>(), + angularVelocity); + + + + absTime += dt; + + var expectedT = tq.SI<NewtonMeter>(); + var torque = expectedT * ratios[gear]; + + var response = new ResponseSuccess(this); + response.Engine.TorqueOutDemand = expectedT; + response.Engine.EngineSpeed = expectedN; + + + + var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, torque, angularVelocity, expectedT, expectedN, + new GearshiftPosition((uint)gear), -double.MaxValue.SI<Second>(), response); + + Assert.AreEqual(newGear, shiftStrategy.NextGear.Gear); + Assert.AreEqual(shiftExpected, shiftRequired); + } + + + + [TestCase(7, 1, 1000, 1400, true)] + [TestCase(7, 2, 400, 200, true)] + public void InitStartGear(int gear, int newGear, double tq, double n, bool shiftExpected) + { + // the first element 0.0 is just a placeholder for axlegear, not used in this test + var ratios = new[] { 0.0, 6.38, 5.2, 4.3, 3.2, 2.5, 1.8, 1, 0.76 }; + var container = GetMocks(ratios, out var runData, out var testPt); + + container.Setup(c => c.VehicleInfo.VehicleSpeed).Returns(0.KMPHtoMeterPerSecond()); + + var gbx = GetMockGearbox(); + Mock.Get(container.Object.EngineInfo).Setup(e => e.EngineSpeed).Returns(() => n.RPMtoRad()); + Mock.Get(container.Object.EngineInfo).Setup(e => e.EngineN95hSpeed).Returns(2000.RPMtoRad()); + + var shiftStrategy = new AMTShiftStrategyOptimized(container.Object); + shiftStrategy.Gearbox = gbx.Object; + + var absTime = 0.SI<Second>(); + var dt = 2.SI<Second>(); + + var expectedN = n.RPMtoRad(); + var angularVelocity = expectedN / ratios[gear]; + + + testPt.Setup(t => t.Gearbox.Request( + It.IsAny<Second>(), + It.IsAny<Second>(), + It.IsAny<NewtonMeter>(), + It.IsAny<PerSecond>(), + true)).Returns(new ResponseDryRun(null) + { + Engine = { + TotalTorqueDemand = 2.SI<NewtonMeter>(), + DynamicFullLoadTorque = 4.SI<NewtonMeter>(), + EngineSpeed = 600.RPMtoRad(), + } + }); + + var gearShiftPosition = shiftStrategy.InitGear(0.SI<Second>(), Constants.SimulationSettings.TargetTimeInterval, 1.SI<NewtonMeter>(), + angularVelocity); + + absTime += dt; + + var expectedT = tq.SI<NewtonMeter>(); + var torque = expectedT * ratios[gear]; + + + //var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, torque, angularVelocity, expectedT, expectedN, + // new GearshiftPosition((uint)gear), -double.MaxValue.SI<Second>(), new ResponseSuccess(this)); + + //Assert.AreEqual(shiftExpected, shiftRequired); + Assert.GreaterOrEqual(shiftStrategy.MaxStartGear.Gear, newGear); + Assert.AreEqual(newGear, shiftStrategy.NextGear.Gear); + } + + + [TestCase(2, 1, 2, 1000, 300)] + [TestCase(3, 2, 2, 1000, 1400)] + [TestCase(8, 7, 2, 1800, 750)] + [TestCase(7, 6, 2, 1800, 750)] + [TestCase(6, 5, 2, 1800, 750)] + [TestCase(5, 4, 2, 1800, 750)] + [TestCase(4, 3, 2, 1800, 750)] + [TestCase(3, 2, 2, 1800, 750)] + [TestCase(2, 2, 2, 1900, 750)] + [TestCase(1, 2, 2, 1200, 700)] + [TestCase(8, 4, 2, 15000, 200)] + [TestCase(2, 2, 2, 300, 1000)] + public void Gearbox_PTO(int gear, int newGear, int ptoGear, double tq, double n) + { + var shiftExpected = gear != newGear; + // the first element 0.0 is just a placeholder for axlegear, not used in this test + var ratios = new[] { 0.0, 6.38, 4.63, 3.44, 2.59, 1.86, 1.35, 1, 0.76 }; + + var container = GetMocks(ratios, out VectoRunData runData, out _); + + runData.DriverData = new DriverData() { + PTODriveRoadsweepingGear = new GearshiftPosition((uint)ptoGear) + }; + + container.Setup(c => c.DrivingCycleInfo.CycleData).Returns( + new CycleData() { + LeftSample = new DrivingCycleData.DrivingCycleEntry() { + PTOActive = PTOActivity.PTOActivityRoadSweeping, + RoadGradient = 0.SI<Radian>(), + } + } + ); + + var shiftStrategy = GetShiftStrategyAndGearbox(container, out var gbx); + + + + ////Mock.Get(container.Object.EngineInfo).Setup(e => e.EngineSpeed).Returns(() => n.RPMtoRad()); + ////Mock.Get(container.Object.EngineInfo).Setup(e => e.EngineN95hSpeed).Returns(2000.RPMtoRad()); + + + + var absTime = 0.SI<Second>(); + var dt = 2.SI<Second>(); + + var expectedN = n.RPMtoRad(); + var angularVelocity = expectedN / ratios[gear]; + + var gearShiftPosition = shiftStrategy.InitGear(0.SI<Second>(), Constants.SimulationSettings.TargetTimeInterval, 1.SI<NewtonMeter>(), + angularVelocity); + + absTime += dt; + + var expectedT = tq.SI<NewtonMeter>(); + var torque = expectedT * ratios[gear]; + + var response = new ResponseSuccess(this) { + + }; + var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, torque, angularVelocity, expectedT, expectedN, + new GearshiftPosition((uint)gear), -double.MaxValue.SI<Second>(), response); + + Assert.AreEqual(shiftExpected, shiftRequired); + Assert.AreEqual(newGear, shiftStrategy.NextGear.Gear); + } + + + private Mock<IVehicleContainer> GetMocks(double[] ratios, + out VectoRunData runData, + out Mock<ITestPowertrain> testPowertrain) + { + runData = GetRunData(ratios); + + var container = GetMockVehicleContainer(runData); + + + //Use simple powertrain to create testpowertrain + testPowertrain = GetMockTestPowertrain(runData, out var simpleContainer); + + + var ptBuilder = new Mock<ISimplePowertrainBuilder>(); + + //TestPowertrain + ptBuilder.Setup(p => p.CreateTestPowertrain( + It.IsAny<IVehicleContainer>(), + It.IsAny<bool>())) + .Returns(testPowertrain.Object); + + ptBuilder.Setup(p => p.CreateTestPowertrain( + It.IsAny<IVehicleContainer>(), + It.IsAny<bool>(), It.IsAny<VectoSimulationJobType>())).Throws(new NotImplementedException()); + + container.Setup(c => c.SimplePowertrainBuilder).Returns(ptBuilder.Object); + + + + return container; + } + + + + + private Mock<ITestPowertrain> GetMockTestPowertrain(VectoRunData runData, out Mock<ISimpleVehicleContainer> simpleContainer) + { + var testPt = new Mock<ITestPowertrain>(); + + simpleContainer = GetSimplePowertrain(runData, out var testGearbox); + testPt.Setup(t => t.Container).Returns(simpleContainer.Object); + + testPt.Setup(t => t.Gearbox).Returns(testGearbox.Object); + // tGbx.Setup(g => g.Initialize(It.IsAny<NewtonMeter>(), It.IsAny<PerSecond>())) + // .Returns((NewtonMeter t, PerSecond n) => new ResponseSuccess(this) { + // Engine = { PowerRequest = n * t, + // EngineSpeed = n }, + // Clutch = { PowerRequest = n * t } + // }); + // tGbx.Setup(g => g.Request(It.IsAny<Second>(), It.IsAny<Second>(), It.IsAny<NewtonMeter>(), It.IsAny<PerSecond>(), + // It.IsAny<bool>())) + // .Returns((Second absTime, Second dt, NewtonMeter t, PerSecond n, bool dryRun) => new ResponseSuccess(this) { + // Engine = { PowerRequest = n * t, EngineSpeed = n }, + // Clutch = { PowerRequest = n * t } + // }); + // tGbx.Setup(g => g.Request(It.IsAny<Second>(), It.IsAny<Second>(), It.IsAny<NewtonMeter>(), It.IsAny<PerSecond>(), + // It.IsAny<bool>())) + // .Returns((Second absTime, Second dt, NewtonMeter t, PerSecond n, bool dryRun) => dryRun ? + // new ResponseDryRun(this) { + // Engine = { + // PowerRequest = n * t, + // EngineSpeed = n, + // TotalTorqueDemand = t, + // }, + // Clutch = { PowerRequest = n * t }, + // DeltaFullLoad = n*t / 2 *(-1) + // }: new ResponseSuccess(this) { + // Engine = { PowerRequest = n * t, EngineSpeed = n }, + // Clutch = { PowerRequest = n * t } + // }); + var tEng = new Mock<ITestpowertrainCombustionEngine>(); + testPt.Setup(t => t.CombustionEngine).Returns(tEng.Object); + tEng.Setup(e => e.EngineStationaryFullPower(It.IsAny<PerSecond>())) + .Returns((PerSecond n) => runData.EngineData.FullLoadCurves[0].FullLoadStationaryPower(n)); + return testPt; + } + + private static Mock<IPowertainInfo> GetPowertrainInfo() + { + var tPi = new Mock<IPowertainInfo>(); + tPi.Setup(p => p.HasCombustionEngine).Returns(true); + return tPi; + } + + private static Mock<IVehicleContainer> GetMockVehicleContainer(VectoRunData runData) + { + var container = new Mock<IVehicleContainer>(); + container.Setup(c => c.RunData).Returns(runData); + var veh = new Mock<IVehicleInfo>(); + veh.Setup(v => v.VehicleSpeed).Returns(10.SI<MeterPerSecond>()); + container.Setup(c => c.VehicleInfo).Returns(veh.Object); + var eng = new Mock<IEngineInfo>(); + container.Setup(c => c.EngineInfo).Returns(eng.Object); + eng.Setup(e => e.EngineIdleSpeed).Returns(runData.EngineData.IdleSpeed); + eng.Setup(e => e.EngineRatedSpeed).Returns(runData.EngineData.FullLoadCurves.First().Value.RatedSpeed); + eng.Setup(e => e.EngineN95hSpeed).Returns(runData.EngineData.FullLoadCurves.First().Value.N95hSpeed); + eng.Setup(e => e.EngineStationaryFullPower(It.IsAny<PerSecond>())) + .Returns((PerSecond n) => runData.EngineData.FullLoadCurves[0].FullLoadStationaryPower(n)); + var ci = new Mock<IDrivingCycleInfo>(); + container.Setup(c => c.DrivingCycleInfo).Returns(ci.Object); + var di = new Mock<IDriverInfo>(); + di.Setup(d => d.DriverBehavior).Returns(DrivingBehavior.Accelerating); + di.Setup(d => d.DrivingAction).Returns(DrivingAction.Accelerate); + container.Setup(c => c.DriverInfo).Returns(di.Object); + ci.Setup(c => c.CycleData).Returns(new CycleData() { LeftSample = new DrivingCycleData.DrivingCycleEntry() { PTOActive = PTOActivity.Inactive } }); + ci.Setup(c => c.CycleLookAhead(It.IsAny<Meter>())).Returns(new DrivingCycleData.DrivingCycleEntry() { + Altitude = 0.SI<Meter>() + }); + ci.Setup(c => c.Altitude).Returns(0.SI<Meter>()); + var pi = new Mock<IPowertainInfo>(); + pi.Setup(p => p.HasCombustionEngine).Returns(true); + container.Setup(c => c.PowertrainInfo).Returns(pi.Object); + var vi = new Mock<IVehicleInfo>(); + vi.Setup(v => v.AirDragResistance(It.IsAny<MeterPerSecond>(), It.IsAny<MeterPerSecond>())) + .Returns(0.SI<Newton>()); + vi.Setup(v => v.RollingResistance(It.IsAny<Radian>())).Returns(0.SI<Newton>()); + vi.Setup(v => v.SlopeResistance(It.IsAny<Radian>())).Returns(0.SI<Newton>()); + vi.Setup(v => v.VehicleSpeed).Returns(30.KMPHtoMeterPerSecond()); + vi.Setup(v => v.TotalMass).Returns(12000.SI<Kilogram>()); + container.Setup(c => c.VehicleInfo).Returns(vi.Object); + var wi = new Mock<IWheelsInfo>(); + container.Setup(c => c.WheelsInfo).Returns(wi.Object); + wi.Setup(w => w.ReducedMassWheels).Returns(0.SI<Kilogram>()); + var axli = new Mock<IAxlegearInfo>(); + container.Setup(c => c.AxlegearInfo).Returns(axli.Object); + axli.Setup(a => a.AxlegearLoss()).Returns(0.SI<Watt>()); + return container; + } + + + private AMTShiftStrategyOptimized GetShiftStrategyAndGearbox(Mock<IVehicleContainer> vehicleContainer, out Mock<IGearbox> gbx) + { + var shiftStrategy = new AMTShiftStrategyOptimized(vehicleContainer.Object); + + + gbx = GetMockGearbox(); + var mockPort = new Mock<ITnOutPort>(); + shiftStrategy.Gearbox = gbx.Object; + + + // NewtonMeter tqRequest = null; + // PerSecond rpmRequest = null; + // mockPort.Setup(p => p.Initialize(It.IsAny<NewtonMeter>(), + // It.IsAny<PerSecond>())).Returns((NewtonMeter tq, PerSecond rpm) => { + // tqRequest = tq; + // rpmRequest = rpm; + // return new ResponseSuccess(this) + // { + // Engine = { + // EngineSpeed = rpm, + // PowerRequest = tq * rpm, + // }, + // }; + // }); + // mockPort.Setup(p => p.Request(It.IsAny<Second>(), It.IsAny<Second>(), It.IsAny<NewtonMeter>(), + // It.IsAny<PerSecond>(), true)).Returns(new ResponseDryRun(this)); + // + // gbx.Connect(mockPort.Object); + + SetVelocityDropLookupData(shiftStrategy); + return shiftStrategy; + } + + + + + private Mock<ISimpleVehicleContainer> GetSimplePowertrain(VectoRunData runData, out Mock<ITestPowertrainTransmission> testGearbox) + { + var simplePt = new Mock<ISimpleVehicleContainer>(); + simplePt.Setup(s => s.RunData).Returns(runData); + simplePt.Setup(s => s.AddComponent(It.IsAny<VectoSimulationComponent>())); + simplePt.Setup(s => s.PowertrainInfo).Returns(GetPowertrainInfo().Object); + simplePt.Setup(s => s.IsTestPowertrain).Returns(true); + + var gbx = GetMockTestGearbox(runData.GearboxData.Gears); + simplePt.Setup(s => s.GearboxInfo).Returns(gbx.Object); + simplePt.Setup(s => s.GearboxCtl).Returns(gbx.Object); + simplePt.Setup(s => s.GearboxOutPort).Returns(gbx.Object); + //Vehicle Info + var vehicleInfo = new Mock<IVehicleInfo>(); + simplePt.Setup(c => c.VehicleInfo).Returns(vehicleInfo.Object); + vehicleInfo.Setup(v => v.VehicleSpeed).Returns(1.KMPHtoMeterPerSecond()); + + //VehiclePort + var vehiclePort = new Mock<IDriverDemandOutPort>(); + vehiclePort.Setup(port => port.Initialize( + It.IsAny<MeterPerSecond>(), It.IsAny<Radian>())).Returns(new ResponseSuccess(this)); + + // simplePt.Setup(c => c).Returns(vehiclePort.Object); + + + //GearboxOutPort + + + // var mockPort = new Mock<ITnOutPort>(); + // mockPort.Name = "MockPort1"; + // mockPort.Setup(p => p.Initialize(It.IsAny<NewtonMeter>(), + // It.IsAny<PerSecond>())).Returns((NewtonMeter tq, PerSecond rpm) => { + // return new ResponseSuccess(this) + // { + // Engine = { + // EngineSpeed = rpm, + // PowerRequest = tq * rpm, + // }, + // }; + // }); + // mockPort.Setup(p => p.Request( + // It.IsAny<Second>(), + // It.IsAny<Second>(), + // It.IsAny<NewtonMeter>(), + // It.IsAny<PerSecond>(), + // true)).Returns(( + // Second absTime, + // Second dt, + // NewtonMeter t, + // PerSecond n, + // bool dryRun) => { + // + // var ratio = + // gbx.Object.Gear == null ? 1.0 : ratios[gbx.Object.Gear.Gear].Ratio; + // return dryRun + // + // ? new ResponseDryRun(this) + // { + // Engine = { + // PowerRequest = n * t, EngineSpeed = n * ratio, + // DynamicFullLoadPower = (t / ratio + 2300.SI<NewtonMeter>()) * n * ratio, + // TotalTorqueDemand = t, + // }, + // Clutch = { PowerRequest = n * t }, + // DeltaFullLoad = n*t / 2 * (-1) + // } + // : new ResponseSuccess(this) + // { + // Engine = { + // PowerRequest = n * t, + // EngineSpeed = n * ratio + // + // }, + // Clutch = { PowerRequest = n * t } + // }; + // }); + + // simplePt.Setup(c => c.GearboxOutPort).Returns(mockPort.Object); + + testGearbox = gbx; + return simplePt; + } + + private Mock<IGearbox> GetMockGearbox() + { + var amtGearbox = new Mock<IAMTGearbox>(MockBehavior.Strict); + amtGearbox.Name = "AMT_Gearbox"; + var gbx = amtGearbox.As<IGearbox>(); + + gbx.Setup(g => g.LastUpshift).Returns(-double.MaxValue.SI<Second>()); + gbx.Setup(g => g.LastDownshift).Returns(-double.MaxValue.SI<Second>()); + return gbx; + } + + + private Mock<ITestPowertrainTransmission> GetMockTestGearbox(Dictionary<uint, GearData> ratios) + { + + Mock<IAMTGearbox> amtGearbox = new Mock<IAMTGearbox>(); + amtGearbox.Name = "AMT_TestGearbox"; + Mock<ITestPowertrainTransmission> gbx = amtGearbox.As<ITestPowertrainTransmission>(); + + + + gbx.Setup(g => g.LastUpshift).Returns(-double.MaxValue.SI<Second>()); + gbx.Setup(g => g.LastDownshift).Returns(-double.MaxValue.SI<Second>()); + + GearshiftPosition gear = null; + gbx.SetupGet(g => g.Gear).Returns(() => { + + return gear; + }); + gbx.SetupSet(g => g.SetGear = It.IsAny<GearshiftPosition>()) + .Callback<GearshiftPosition>(p => { + gear = p; + }); + + + GearshiftPosition nextGear = null; + gbx.SetupGet(g => g.NextGear).Returns(() => nextGear); + gbx.SetupSet(g => g.SetNextGear = It.IsAny<GearshiftPosition>()) + .Callback<GearshiftPosition>(p => nextGear = p); + + gbx.Setup(p => p.Initialize(It.IsAny<NewtonMeter>(), + It.IsAny<PerSecond>())).Returns((NewtonMeter tq, PerSecond rpm) => { + return new ResponseSuccess(this) + { + Engine = { + EngineSpeed = rpm, + PowerRequest = tq * rpm, + }, + }; + }); + gbx.Setup(p => p.Request( + It.IsAny<Second>(), + It.IsAny<Second>(), + It.IsAny<NewtonMeter>(), + It.IsAny<PerSecond>(), + true)).Returns(( + Second absTime, + Second dt, + NewtonMeter t, + PerSecond n, + bool dryRun) => { + + var ratio = + gbx.Object.Gear == null ? 1.0 : ratios[gbx.Object.Gear.Gear].Ratio; + return dryRun + ? new ResponseDryRun(this) { + Engine = { + PowerRequest = n * t, EngineSpeed = n * ratio, + DynamicFullLoadPower = (t / ratio + 2300.SI<NewtonMeter>()) * n * ratio, + TotalTorqueDemand = t, + }, + Clutch = { PowerRequest = n * t }, + DeltaFullLoad = n * t / 2 * (-1) + } + : new ResponseSuccess(this) { + Engine = { + PowerRequest = n * t, + EngineSpeed = n * ratio + + }, + Clutch = { PowerRequest = n * t } + }; + }); + return gbx; + } + + + private void SetVelocityDropLookupData(AMTShiftStrategyOptimized shiftStrategy) + { + //"StartVelocity [km/h], Gradient [-], EndVelocity [km/h]" + var data = new[] { + new[] { 5.0, -0.0997, 9.061522965237558 }, + new[] { 5.0, -0.0798, 7.76698080079411 }, + new[] { 5.0, -0.0599, 6.46583777913701 }, + new[] { 5.0, -0.0400, 5.1596021788785045 }, + new[] { 5.0, -0.0200, 3.8498121019126907 }, + new[] { 5.0, 0.0000, 2.5380265159468918 }, + new[] { 5.0, 0.0200, 1.2258160477557427 }, + new[] { 5.0, 0.0400, 0.0 }, + new[] { 5.0, 0.0599, 0.0 }, + new[] { 5.0, 0.0798, 0.0 }, + new[] { 5.0, 0.0997, 0.0 }, + new[] { 10.0, -0.0997, 14.807789640888302 }, + new[] { 10.0, -0.0798, 13.474253785811362 }, + new[] { 10.0, -0.0599, 12.133880027250777 }, + new[] { 10.0, -0.0400, 10.788221550084467 }, + new[] { 10.0, -0.0200, 9.438862432338068 }, + new[] { 10.0, 0.0000, 8.087408432114643 }, + new[] { 10.0, 0.0200, 6.735477499784416 }, + new[] { 10.0, 0.0400, 5.384690105076845 }, + new[] { 10.0, 0.0599, 4.036659549786269 }, + new[] { 10.0, 0.0798, 2.6929823705748137 }, + new[] { 10.0, 0.0997, 1.3552289800549435 }, + new[] { 20.0, -0.0997, 25.061542153872097 }, + new[] { 20.0, -0.0798, 23.72002987685605 }, + new[] { 20.0, -0.0599, 22.371630788642932 }, + new[] { 20.0, -0.0400, 21.017907257116025 }, + new[] { 20.0, -0.0200, 19.660452757813403 }, + new[] { 20.0, 0.0000, 18.30088261992287 }, + new[] { 20.0, 0.0200, 16.94082447048767 }, + new[] { 20.0, 0.0400, 15.581908518759507 }, + new[] { 20.0, 0.0599, 14.225757795590708 }, + new[] { 20.0, 0.0798, 12.873978508374211 }, + new[] { 20.0, 0.0997, 11.528150617530041 }, + new[] { 30.000000000000004, -0.0997, 35.091774208140095 }, + new[] { 30.000000000000004, -0.0798, 33.750904327320896 }, + new[] { 30.000000000000004, -0.0599, 32.40315158162777 }, + new[] { 30.000000000000004, -0.0400, 31.050077596965064 }, + new[] { 30.000000000000004, -0.0200, 29.69327509188113 }, + new[] { 30.000000000000004, 0.0000, 28.33435862498606 }, + new[] { 30.000000000000004, 0.0200, 26.974955046566407 }, + new[] { 30.000000000000004, 0.0400, 25.616693776603913 }, + new[] { 30.000000000000004, 0.0599, 24.261197065863925 }, + new[] { 30.000000000000004, 0.0798, 22.91007034016412 }, + new[] { 30.000000000000004, 0.0997, 21.56489279686667 }, + new[] { 40.0, -0.0997, 45.024018797189854 }, + new[] { 40.0, -0.0798, 43.68636622428101 }, + new[] { 40.0, -0.0599, 42.34185052441486 }, + new[] { 40.0, -0.0400, 40.99202962224952 }, + new[] { 40.0, -0.0200, 39.63849244500093 }, + new[] { 40.0, 0.0000, 38.282849690992855 }, + new[] { 40.0, 0.0200, 36.926724305651554 }, + new[] { 40.0, 0.0400, 35.57174178507285 }, + new[] { 40.0, 0.0599, 34.21952045137207 }, + new[] { 40.0, 0.0798, 32.87166183129923 }, + new[] { 40.0, 0.0997, 31.5297412694979 }, + new[] { 50.0, -0.0997, 54.652157586769704 }, + new[] { 50.0, -0.0798, 53.319266704395716 }, + new[] { 50.0, -0.0599, 51.97954186606304 }, + new[] { 50.0, -0.0400, 50.634535516787736 }, + new[] { 50.0, -0.0200, 49.28583097196263 }, + new[] { 50.0, 0.0000, 47.93503321632867 }, + new[] { 50.0, 0.0200, 46.583759417454765 }, + new[] { 50.0, 0.0400, 45.23362925944123 }, + new[] { 50.0, 0.0599, 43.88625525588574 }, + new[] { 50.0, 0.0798, 42.54323315977748 }, + new[] { 50.0, 0.0997, 41.20613261641401 }, + new[] { 60.00000000000001, -0.0997, 64.2503607025971 }, + new[] { 60.00000000000001, -0.0798, 62.91932863058169 }, + new[] { 60.00000000000001, -0.0599, 61.58156853535776 }, + new[] { 60.00000000000001, -0.0400, 60.23862904729555 }, + new[] { 60.00000000000001, -0.0200, 58.89369896300112 }, + new[] { 60.00000000000001, 0.0000, 57.547040626925885 }, + new[] { 60.00000000000001, 0.0200, 56.199911833784675 }, + new[] { 60.00000000000001, 0.0400, 54.85392730356455 }, + new[] { 60.00000000000001, 0.0599, 53.510694584916905 }, + new[] { 60.00000000000001, 0.0798, 52.17180450267632 }, + new[] { 60.00000000000001, 0.0997, 50.83882182989668 }, + new[] { 70.0, -0.0997, 73.78388063954164 }, + new[] { 70.0, -0.0798, 72.45700102808648 }, + new[] { 70.0, -0.0599, 71.12341092304165 }, + new[] { 70.0, -0.0400, 69.78459543842656 }, + new[] { 70.0, -0.0200, 68.44188526693415 }, + new[] { 70.0, 0.0000, 67.09719334997524 }, + new[] { 70.0, 0.0200, 65.75212749798493 }, + new[] { 70.0, 0.0400, 64.40829754257321 }, + new[] { 70.0, 0.0599, 63.06730571969745 }, + new[] { 70.0, 0.0798, 61.73073716025881 }, + new[] { 70.0, 0.0997, 60.40015062055851 }, + new[] { 80.0, -0.0997, 83.25457689135129 }, + new[] { 80.0, -0.0798, 81.93182852399568 }, + new[] { 80.0, -0.0599, 80.60238880559001 }, + new[] { 80.0, -0.0400, 79.2676325992058 }, + new[] { 80.0, -0.0200, 77.92916666616652 }, + new[] { 80.0, 0.0000, 76.58872134590663 }, + new[] { 80.0, 0.0200, 75.24790011046437 }, + new[] { 80.0, 0.0400, 73.90830846424944 }, + new[] { 80.0, 0.0599, 72.57154434889891 }, + new[] { 80.0, 0.0798, 71.23918865436896 }, + new[] { 80.0, 0.0997, 69.91277394305271 }, + }; + var entries = new List<VelocitySpeedGearshiftPreprocessor.Entry>(); + foreach (var d in data) + { + entries.Add(new VelocitySpeedGearshiftPreprocessor.Entry() + { + StartVelocity = d[0].KMPHtoMeterPerSecond(), + Gradient = d[1].SI<Radian>(), + EndVelocity = d[2].KMPHtoMeterPerSecond(), + }); + } + + shiftStrategy.VelocityDropData.Data = entries.ToArray(); + + } + + private static VectoRunData GetRunData(double[] ratios) + { + var gearboxData = new GearboxData { + Gears = new Dictionary<uint, GearData>() + }; + for (uint i = 1; i < ratios.Length; i++) { + gearboxData.Gears[i] = new GearData { + Ratio = ratios[i], + LossMap = TransmissionLossMapReader.Create(0.96, ratios[i], $"Gear {i}") + }; + } + + IEnumerable<(uint key, EngineFullLoadCurve fld)> fldCurves = + ratios.Select( + (_, i) => ((uint)i, + FullLoadCurveReader.Create(InputDataHelper.InputDataAsTableData(EngineFldHdr, EngineFldData)) + )); + + + List<CombustionEngineFuelData> fuels = new List<CombustionEngineFuelData>() { + new CombustionEngineFuelData() { + ColdHotCorrectionFactor = 1, + ConsumptionMap = FuelConsumptionMapReader.Create(InputDataHelper.InputDataAsTableData( + EngineFcMapHdr, + EngineFcMapData)), + FuelData = FuelData.Diesel, + } + }; + var engineData = new CombustionEngineData() { + IdleSpeed = 560.RPMtoRad(), + FullLoadCurves = fldCurves.ToDictionary((x) => x.key, (x) => x.fld), + Fuels = fuels, + }; + + var axlRatio = 3.240355; + var gearsInput = gearboxData.Gears.Select(x => { + var r = new Mock<ITransmissionInputData>(); + r.Setup(g => g.Ratio).Returns(x.Value.Ratio); + return r.Object; + }).ToList(); + foreach (var entry in gearboxData.Gears) { + entry.Value.ShiftPolygon = DeclarationData.Gearbox.ComputeManualTransmissionShiftPolygon( + (int)(entry.Key - 1), engineData.FullLoadCurves.First().Value, + gearsInput, engineData, axlRatio, 0.5.SI<Meter>()); + } + + + var mockCycle = new Mock<IDrivingCycleData>(); + mockCycle.Setup(cd => cd.Entries).Returns( + new List<DrivingCycleData.DrivingCycleEntry>() { + new DrivingCycleData.DrivingCycleEntry() { + RoadGradient = 0.SI<Radian>() + } + }); + + + + + + + + + + var runData = new VectoRunData() { + GearboxData = gearboxData, + GearshiftParameters = new ShiftStrategyParameters() { + StartSpeed = 2.SI<MeterPerSecond>(), + TimeBetweenGearshifts = 6.SI<Second>(), + DownshiftAfterUpshiftDelay = 2.SI<Second>(), + UpshiftAfterDownshiftDelay = 2.SI<Second>(), + UpshiftMinAcceleration = 0.1.SI<MeterPerSquareSecond>(), + StartTorqueReserve = 0.2, + }, + EngineData = engineData, + AxleGearData = new AxleGearData() { + AxleGear = new TransmissionData() { + Ratio = 3.240355 + } + }, + VehicleData = new VehicleData() { + DynamicTyreRadius = 0.492.SI<Meter>(), + }, + Cycle = mockCycle.Object, + }; + return runData; + } + + const string EngineFldHdr = "engine speed [1/min],full load torque [Nm],motoring torque [Nm],PT1 [s]"; + + static readonly string[] EngineFldData = new[] { + "560,1180,-149,0.6 ", + "600,1282,-148,0.6 ", + "799.9999999,1791,-149,0.6 ", + "1000,2300,-160,0.6 ", + "1200,2300,-179,0.6 ", + "1400,2300,-203,0.6 ", + "1599.999999,2079,-235,0.49", + "1800,1857,-264,0.25 ", + "2000.000001,1352,-301,0.25", + "2100,1100,-320,0.25 ", + }; + + + const string EngineFcMapHdr = "engine speed [rpm], torque [Nm], fuel consumption [g/h]"; + static readonly string[] EngineFcMapData = new[] { + "500,-235.5,0", +"500,-135.5,0", +"500,0,1355", +"500,213.4,3412.291", +"500,426.8,5830.1", +"500,640.2,8316.426", +"500,853.6,10439.87", +"500,1067,12823.69", +"500,1188,14228.79", +"500,1401.4,16628.66", +"600,-238,0", +"600,-138,0", +"600,0,1355", +"600,213.4,3412.291", +"600,426.8,5830.1", +"600,640.2,8316.426", +"600,853.6,10439.87", +"600,1067,12823.69", +"600,1188,14228.79", +"600,1401.4,16628.66", +"751,-241.775,0", +"751,-141.775,0", +"750.9,0,1649.255", +"750.9,213.4,4157.795", +"750.9,426.8,7149.494", +"750.9,640.2,10037.08", +"750.9,853.6,12957.07", +"750.9,1067,16055.22", +"750.9,1280.4,19231.36", +"750.9,1493.8,22400.17", +"750.9,1544.879,23213.92", +"751,1758.279,26392.93", +"902,-247.59,0", +"902,-147.59,0", +"901.8,0,2210.735", +"901.8,213.4,5204.867", +"901.8,426.8,8515.462", +"901.8,640.2,11804.75", +"901.8,853.6,15410.55", +"901.8,1067,19081.7", +"901.8,1280.4,22742.96", +"901.8,1493.8,26543.87", +"901.8,1707.2,30534.68", +"901.8,1901.757,34352.75", +"902,2115.157,38403.27", +"1053,-255.445,0", +"1053,-155.445,0", +"1052.7,0,2768.035", +"1052.7,213.4,6228.407", +"1052.7,426.8,9836.041", +"1052.7,640.2,13624.5", +"1052.7,853.6,17854.95", +"1052.7,1067,22072.71", +"1052.7,1280.4,26161.13", +"1052.7,1493.8,30525.55", +"1052.7,1707.2,35019.18", +"1052.7,1920.6,39913.3", +"1052.7,2134,45438.16", +"1053,2347.4,50542.53", +"1204,-265.44,0", +"1203.6,0,3086.704", +"1203.6,213.4,6943.027", +"1203.6,426.8,11040.37", +"1203.6,640.2,15504.65", +"1203.6,853.6,20335.89", +"1203.6,1067,25176.6", +"1203.6,1280.4,29782.22", +"1203.6,1493.8,34642.24", +"1203.6,1707.2,39786.14", +"1203.6,1920.6,45254.8", +"1203.6,2134,51129.03", +"1204,2347.4,56732.88", +"1367,-283.37,0", +"1367,-183.37,0", +"1367.1,0,3845.344", +"1367.1,213.4,7981.742", +"1367.1,426.8,12796.69", +"1367.1,640.2,17789.2", +"1367.1,853.6,22854.21", +"1367.1,1067,28302.84", +"1367.1,1280.4,33739.91", +"1367.1,1493.8,39393.87", +"1367.1,1707.2,45836.33", +"1367.1,1920.6,52078.71", +"1367.1,2134,58296.41", +"1367,2347.4,64530.56", +"1490,-300.5,0", +"1490,-200.5,0", +"1489.6,0,4373.424", +"1489.6,213.4,8861.484", +"1489.6,426.8,14090.86", +"1489.6,640.2,19518.29", +"1489.6,853.6,25092.8", +"1489.6,1067,30873.69", +"1489.6,1280.4,36865.42", +"1489.6,1493.8,43095.57", +"1489.6,1707.2,50249.81", +"1489.6,1920.6,57035.25", +"1489.6,2041.712,60609.5", +"1490,2255.112,67311.83", +"1612,-318.62,0", +"1612,-218.62,0", +"1612.2,0,4904.015", +"1612.2,213.4,9810.482", +"1612.2,426.8,15403.9", +"1612.2,640.2,21301.35", +"1612.2,853.6,27492.32", +"1612.2,1067,33580.96", +"1612.2,1280.4,40114.61", +"1612.2,1493.8,46914.77", +"1612.2,1707.2,54666.14", +"1612.2,1915.434,61862.91", +"1612,2128.834,69491.99", +"1735,-335.225,0", +"1735,-235.225,0", +"1734.7,0,5586.953", +"1734.7,213.4,11041.15", +"1734.7,426.8,16949.24", +"1734.7,640.2,23500.23", +"1734.7,853.6,30159.59", +"1734.7,1067,36741.18", +"1734.7,1280.4,43923.85", +"1734.7,1493.8,51295.21", +"1734.7,1707.2,59469.31", +"1734.7,1789.259,62731.31", +"1735,2002.659,70935.23", +"1857,-353.69,0", +"1857,-253.69,0", +"1857.3,0,6673.839", +"1857.3,213.4,12518.56", +"1857.3,426.8,18687.88", +"1857.3,640.2,25652.39", +"1857.3,853.6,33003.08", +"1857.3,1067,40438.09", +"1857.3,1280.4,48117.52", +"1857.3,1493.8,55848.59", +"1857.3,1587.631,59434.17", +"1857,1801.031,67215.39", +"1957,-370.69,0", +"1957,-270.69,0", +"1957.3,0,6673.839", +"1957.3,213.4,12518.56", +"1957.3,426.8,18687.88", +"1957.3,640.2,25652.39", +"1957.3,853.6,33003.08", +"1957.3,1067,40438.09", +"1957.3,1280.4,48117.52", +"1957.3,1493.8,55848.59", +"1957.3,1587.631,59434.17", +"1957,1801.031,67215.39", + }; + + +} \ No newline at end of file -- GitLab From 8d12c22d4134adc52cccc9dd24ae009f66e1854c Mon Sep 17 00:00:00 2001 From: "VKMTHD\\haraldmartini" <martini@ivt.tugraz.at> Date: Thu, 13 Mar 2025 10:53:06 +0100 Subject: [PATCH 05/22] updated ptBuilder mock --- .../GearShiftStrategy/AMTShiftStrategyTests.cs | 13 ++++++++----- .../GearShiftStrategy/ATShiftStrategyTests.cs | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/AMTShiftStrategyTests.cs b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/AMTShiftStrategyTests.cs index 13d05f4e4a..19c047ba8c 100644 --- a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/AMTShiftStrategyTests.cs +++ b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/AMTShiftStrategyTests.cs @@ -45,7 +45,7 @@ TestCase(8, 4, 15000, 200, true),] var testPt = GetMockTestPowertrain(runData); var ptBuilder = new Mock<ISimplePowertrainBuilder>(); - ptBuilder.Setup(p => p.CreateTestPowertrain(It.IsAny<IVehicleContainer>(), It.IsAny<bool>(), It.IsAny<VectoSimulationJobType?>())) + ptBuilder.Setup(p => p.CreateTestPowertrain(It.IsAny<IVehicleContainer>(), It.IsAny<bool>())) .Returns(testPt.Object); container.Setup(c => c.SimplePowertrainBuilder).Returns(ptBuilder.Object); @@ -95,7 +95,8 @@ TestCase(8, 4, 15000, 200, true),] var testPt = GetMockTestPowertrain(runData); var ptBuilder = new Mock<ISimplePowertrainBuilder>(); - ptBuilder.Setup(p => p.CreateTestPowertrain(It.IsAny<IVehicleContainer>(), It.IsAny<bool>(), It.IsAny<VectoSimulationJobType?>())) + ptBuilder.Setup(p => p.CreateTestPowertrain(It.IsAny<IVehicleContainer>(), + It.IsAny<bool>())) .Returns(testPt.Object); container.Setup(c => c.SimplePowertrainBuilder).Returns(ptBuilder.Object); @@ -158,7 +159,9 @@ TestCase(8, 4, 15000, 200, true),] var testPt = GetMockTestPowertrain(runData); var ptBuilder = new Mock<ISimplePowertrainBuilder>(); - ptBuilder.Setup(p => p.CreateTestPowertrain(It.IsAny<IVehicleContainer>(), It.IsAny<bool>(), It.IsAny<VectoSimulationJobType?>())) + ptBuilder.Setup(p => p.CreateTestPowertrain( + It.IsAny<IVehicleContainer>(), + It.IsAny<bool>())) .Returns(testPt.Object); container.Setup(c => c.SimplePowertrainBuilder).Returns(ptBuilder.Object); @@ -206,7 +209,7 @@ TestCase(8, 4, 15000, 200, true),] var testPt = GetMockTestPowertrain(runData); var ptBuilder = new Mock<ISimplePowertrainBuilder>(); - ptBuilder.Setup(p => p.CreateTestPowertrain(It.IsAny<IVehicleContainer>(), It.IsAny<bool>(), It.IsAny<VectoSimulationJobType?>())) + ptBuilder.Setup(p => p.CreateTestPowertrain(It.IsAny<IVehicleContainer>(), It.IsAny<bool>())) .Returns(testPt.Object); container.Setup(c => c.SimplePowertrainBuilder).Returns(ptBuilder.Object); @@ -294,7 +297,7 @@ TestCase(8, 4, 15000, 200, true),] var testPt = GetMockTestPowertrain(runData); var ptBuilder = new Mock<ISimplePowertrainBuilder>(); - ptBuilder.Setup(p => p.CreateTestPowertrain(It.IsAny<IVehicleContainer>(), It.IsAny<bool>(), It.IsAny<VectoSimulationJobType?>())) + ptBuilder.Setup(p => p.CreateTestPowertrain(It.IsAny<IVehicleContainer>(), It.IsAny<bool>())) .Returns(testPt.Object); container.Setup(c => c.SimplePowertrainBuilder).Returns(ptBuilder.Object); diff --git a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyTests.cs b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyTests.cs index fa6040c0cc..0e1b66fe18 100644 --- a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyTests.cs +++ b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyTests.cs @@ -148,7 +148,7 @@ public class ATShiftStrategyTests engineInfo.Setup(e => e.EngineIdleSpeed).Returns(600.RPMtoRad()); engineInfo.Setup(e => e.EngineRatedSpeed).Returns(2000.RPMtoRad()); - ptBuilder.Setup(b => b.CreateTestPowertrain(It.IsAny<IVehicleContainer>(), It.IsAny<bool>(), It.IsAny<VectoSimulationJobType?>())).Returns(testPt.Object); + ptBuilder.Setup(b => b.CreateTestPowertrain(It.IsAny<IVehicleContainer>(), It.IsAny<bool>())).Returns(testPt.Object); testPt.Setup(t => t.Gearbox).Returns(testGbx.Object); testPt.Setup(t => t.Container).Returns(testContainer.Object); -- GitLab From d42d5a573329f1a16960b6ed48dcf623668ddd14 Mon Sep 17 00:00:00 2001 From: "VKMTHD\\haraldmartini" <martini@ivt.tugraz.at> Date: Thu, 13 Mar 2025 13:40:21 +0100 Subject: [PATCH 06/22] renamed ATShiftStrategyTests.cs to ATShiftStrategyOptimizedTests.cs --- ...ATShiftStrategyTests.cs => ATShiftStrategyOptimizedTests.cs} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/{ATShiftStrategyTests.cs => ATShiftStrategyOptimizedTests.cs} (99%) diff --git a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyTests.cs b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyOptimizedTests.cs similarity index 99% rename from Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyTests.cs rename to Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyOptimizedTests.cs index 0e1b66fe18..01ef757c55 100644 --- a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyTests.cs +++ b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyOptimizedTests.cs @@ -24,7 +24,7 @@ using Assert = NUnit.Framework.Assert; namespace TUGraz.Vecto.UnitTests.TestCases.Components.GearShiftStrategy; -public class ATShiftStrategyTests +public class ATShiftStrategyOptimizedTests { [Test, TestCase(0, 100, 1), -- GitLab From 835fc504eb117ebaf8d007b317a47b9604e18b80 Mon Sep 17 00:00:00 2001 From: "VKMTHD\\haraldmartini" <martini@ivt.tugraz.at> Date: Thu, 13 Mar 2025 14:07:25 +0100 Subject: [PATCH 07/22] Revert "renamed ATShiftStrategyTests.cs to ATShiftStrategyOptimizedTests.cs" This reverts commit d42d5a573329f1a16960b6ed48dcf623668ddd14. --- ...ATShiftStrategyOptimizedTests.cs => ATShiftStrategyTests.cs} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/{ATShiftStrategyOptimizedTests.cs => ATShiftStrategyTests.cs} (99%) diff --git a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyOptimizedTests.cs b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyTests.cs similarity index 99% rename from Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyOptimizedTests.cs rename to Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyTests.cs index 01ef757c55..0e1b66fe18 100644 --- a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyOptimizedTests.cs +++ b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyTests.cs @@ -24,7 +24,7 @@ using Assert = NUnit.Framework.Assert; namespace TUGraz.Vecto.UnitTests.TestCases.Components.GearShiftStrategy; -public class ATShiftStrategyOptimizedTests +public class ATShiftStrategyTests { [Test, TestCase(0, 100, 1), -- GitLab From 01e070a98dff5ca808fdde2b38e511a487e2f90f Mon Sep 17 00:00:00 2001 From: "VKMTHD\\haraldmartini" <martini@ivt.tugraz.at> Date: Thu, 13 Mar 2025 14:36:33 +0100 Subject: [PATCH 08/22] add params keyword to input helper --- Testing/UnitTests/Vecto UnitTests/Utils/InputDataHelper.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Testing/UnitTests/Vecto UnitTests/Utils/InputDataHelper.cs b/Testing/UnitTests/Vecto UnitTests/Utils/InputDataHelper.cs index 7021f9b29c..424a7e7ea0 100644 --- a/Testing/UnitTests/Vecto UnitTests/Utils/InputDataHelper.cs +++ b/Testing/UnitTests/Vecto UnitTests/Utils/InputDataHelper.cs @@ -50,11 +50,10 @@ namespace TUGraz.VectoCore.Tests.Utils return cycleData; } - public static TableData InputDataAsTableData(string header, string[] entries) + public static TableData InputDataAsTableData(string header, params string[] entries) { return VectoCSVFile.ReadStream(InputDataAsStream(header, entries)); } - public static string GetRandomFilename(string jobFile) { var path = Path.GetDirectoryName(Path.GetFullPath(jobFile)); -- GitLab From 285f9c397bba34d11c86b60ca7d9ee245be66f6e Mon Sep 17 00:00:00 2001 From: "VKMTHD\\haraldmartini" <martini@ivt.tugraz.at> Date: Thu, 13 Mar 2025 15:47:19 +0100 Subject: [PATCH 09/22] add Initialize Method to IAPTGearbox Interface --- VectoCore/VectoCore/Models/SimulationComponent/IGearbox.cs | 5 +++++ .../Models/SimulationComponent/Impl/Gearbox/APTGearbox.cs | 3 +-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/VectoCore/VectoCore/Models/SimulationComponent/IGearbox.cs b/VectoCore/VectoCore/Models/SimulationComponent/IGearbox.cs index 138d035dff..e8516d48e2 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/IGearbox.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/IGearbox.cs @@ -29,6 +29,9 @@ * Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology */ +using TUGraz.VectoCommon.Models; +using TUGraz.VectoCommon.Utils; +using TUGraz.VectoCore.Models.Connector.Ports.Impl; using TUGraz.VectoCore.Models.Simulation.DataBus; using TUGraz.VectoCore.Models.SimulationComponent.Impl; using TUGraz.VectoCore.Models.SimulationComponent.Impl.Gearbox; @@ -54,6 +57,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent ATGearboxState GetPreviousState { get; } bool ShiftToLocked { get; } IIdleController IdleController { set; } + ResponseDryRun Initialize(GearshiftPosition gear, NewtonMeter outTorque, + PerSecond outAngularVelocity); } public interface IAPTNGearbox : IGearboxType { } diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Gearbox/APTGearbox.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Gearbox/APTGearbox.cs index ef23b916fa..c5e91915bb 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Gearbox/APTGearbox.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Gearbox/APTGearbox.cs @@ -195,8 +195,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Gearbox } - - internal ResponseDryRun Initialize(GearshiftPosition gear, NewtonMeter outTorque, + public ResponseDryRun Initialize(GearshiftPosition gear, NewtonMeter outTorque, PerSecond outAngularVelocity) { var effectiveRatio = gear.TorqueConverterLocked.Value -- GitLab From 36fea454c692b8d502b46baa03daa6f3e48e5d14 Mon Sep 17 00:00:00 2001 From: "VKMTHD\\haraldmartini" <martini@ivt.tugraz.at> Date: Sun, 16 Mar 2025 14:38:51 +0100 Subject: [PATCH 10/22] let IGearboxType implement IGearbox --- VectoCore/VectoCore/Models/SimulationComponent/IGearbox.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VectoCore/VectoCore/Models/SimulationComponent/IGearbox.cs b/VectoCore/VectoCore/Models/SimulationComponent/IGearbox.cs index e8516d48e2..b422e53999 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/IGearbox.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/IGearbox.cs @@ -43,7 +43,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent /// </summary> public interface IGearbox : IPowerTrainComponent, IGearboxInfo, IGearboxControl, IUpdateable { } - public interface IGearboxType {} + public interface IGearboxType : IGearbox {} public interface IMTGearbox : IGearboxType {} -- GitLab From 202ed33b200a787cfbe656dae0edcefeb8bb5adc Mon Sep 17 00:00:00 2001 From: "VKMTHD\\haraldmartini" <martini@ivt.tugraz.at> Date: Sun, 16 Mar 2025 14:40:44 +0100 Subject: [PATCH 11/22] MTShiftStrategy: Use testpowertrain for dry run requessts added MTShiftStrategyTests --- .../GearShiftStrategy/MTShiftStrategyTests.cs | 689 ++++++++++++++++++ .../Impl/Shiftstrategies/MTShiftStrategy.cs | 37 +- 2 files changed, 714 insertions(+), 12 deletions(-) create mode 100644 Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/MTShiftStrategyTests.cs diff --git a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/MTShiftStrategyTests.cs b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/MTShiftStrategyTests.cs new file mode 100644 index 0000000000..098055db3f --- /dev/null +++ b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/MTShiftStrategyTests.cs @@ -0,0 +1,689 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Moq; +using NUnit.Framework; +using TUGraz.VectoCommon.InputData; +using TUGraz.VectoCommon.Models; +using TUGraz.VectoCommon.Utils; +using TUGraz.VectoCore.Configuration; +using TUGraz.VectoCore.InputData.Reader.ComponentData; +using TUGraz.VectoCore.Models.Connector.Ports.Impl; +using TUGraz.VectoCore.Models.Declaration; +using TUGraz.VectoCore.Models.Simulation; +using TUGraz.VectoCore.Models.Simulation.Data; +using TUGraz.VectoCore.Models.Simulation.DataBus; +using TUGraz.VectoCore.Models.SimulationComponent; +using TUGraz.VectoCore.Models.SimulationComponent.Data; +using TUGraz.VectoCore.Models.SimulationComponent.Data.Engine; +using TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox; +using TUGraz.VectoCore.Models.SimulationComponent.Impl; +using TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies; +using TUGraz.VectoCore.Tests.Utils; + +namespace TUGraz.Vecto.UnitTests.TestCases.Components.GearShiftStrategy; + +public class MTShiftStrategyTests +{ + [TestCase(1, 2, 1000, 1500)] + [TestCase(1, 6, 200, 8000)] + [TestCase(2, 4, 800, 1400)] + [TestCase(7, 8, 1000, 1400)] + [TestCase(6, 8, 800, 1400)] + [TestCase(5, 6, 1000, 1300)] + [TestCase(4, 5, 1000, 1400)] + [TestCase(3, 4, 1000, 1400)] + [TestCase(8, 8, 1000, 1400)] + public void Gearbox_ShiftUp(int gear, int newGear, double tq_Nm, double n_RPM) + { + var shiftExpected = gear != newGear; + + var gearRatios = new[] { 0.0, 6.38, 4.63, 3.44, 2.59, 1.86, 1.35, 1, 0.76 }; + + + var container = GetMocks(n_RPM, gearRatios, + out var runData, + out var info, + out var testPt, + out var ptBuilder); + + + var shiftStrategy = GetShiftStrategyAndGearbox(container, out _); + + + + var absTime = 0.SI<Second>(); + var dt = 2.SI<Second>(); + + + var expectedN = n_RPM.RPMtoRad(); + var angularVelocity = expectedN / gearRatios[gear]; + + var gearShiftPosition = shiftStrategy.InitGear(0.SI<Second>(), Constants.SimulationSettings.TargetTimeInterval, 1.SI<NewtonMeter>(), + angularVelocity); + + var expectedT = tq_Nm.SI<NewtonMeter>(); + var torque = expectedT * gearRatios[gear]; + var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, torque, angularVelocity, expectedT, expectedN, + new GearshiftPosition((uint)gear), -double.MaxValue.SI<Second>(), new ResponseSuccess(this)); + Assert.AreEqual(newGear, shiftStrategy.NextGear.Gear); + Assert.AreEqual(shiftExpected, shiftRequired); + } + + + [TestCase(2, 1, 1000, 300)] + [TestCase(3, 4, 1000, 1400)] + [TestCase(8, 7, 1800, 750)] + [TestCase(7, 6, 1800, 750)] + [TestCase(6, 5, 1800, 750)] + [TestCase(5, 4, 1800, 750)] + [TestCase(4, 3, 1800, 750)] + [TestCase(3, 2, 1800, 750)] + [TestCase(2, 1, 1900, 750)] + [TestCase(1, 1, 1200, 700)] + [TestCase(8, 4, 15000, 200)] + public void Gearbox_ShiftDown(int gear, int newGear, double tq_Nm, double n_RPM) + { + var shiftExpected = gear != newGear; + + var gearRatios = new[] { 0.0, 6.38, 4.63, 3.44, 2.59, 1.86, 1.35, 1, 0.76 }; + + var container = GetMocks(n_RPM, gearRatios, + out var runData, + out var info, + out var testPt, + out var ptBuilder); + + + var shiftStrategy = GetShiftStrategyAndGearbox(container, out _); + + var absTime = 0.SI<Second>(); + var dt = 2.SI<Second>(); + + + var expectedN = n_RPM.RPMtoRad(); + var angularVelocity = expectedN / gearRatios[gear]; + + var gearShiftPosition = shiftStrategy.InitGear(0.SI<Second>(), Constants.SimulationSettings.TargetTimeInterval, 1.SI<NewtonMeter>(), + angularVelocity); + + var expectedT = tq_Nm.SI<NewtonMeter>(); + var torque = expectedT * gearRatios[gear]; + var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, torque, angularVelocity, expectedT, expectedN, + new GearshiftPosition((uint)gear), -double.MaxValue.SI<Second>(), new ResponseSuccess(this)); + Assert.AreEqual(newGear, shiftStrategy.NextGear.Gear); + Assert.AreEqual(shiftExpected, shiftRequired); + } + + [TestCase(2, 1,2, 1000, 300)] + [TestCase(3, 2,2, 1000, 1400)] + [TestCase(8, 7,2, 1800, 750)] + [TestCase(7, 6,2, 1800, 750)] + [TestCase(6, 5,2, 1800, 750)] + [TestCase(5, 4,2, 1800, 750)] + [TestCase(4, 3,2, 1800, 750)] + [TestCase(3, 2,2, 1800, 750)] + [TestCase(2, 2,2, 1900, 750)] + [TestCase(1, 2,2, 1200, 700)] + [TestCase(8, 4,2, 15000, 200)] + [TestCase(2, 2, 2, 300, 1000)] + public void Gearbox_PTO(int gear, int newGear, int ptoGear, double tq_Nm, double n_RPM) + { + var shiftExpected = gear != newGear; + + var gearRatios = new[] { 0.0, 6.38, 4.63, 3.44, 2.59, 1.86, 1.35, 1, 0.76 }; + var container = GetMocks( + n_RPM: n_RPM, + gearRatios: gearRatios, + runData: out var runData, + info: out _, + testPt: out _, + ptBuilder: out _); + + //Cycle Info + var cycleInfo = new Mock<IDrivingCycleInfo>(); + container.Setup(c => c.DrivingCycleInfo).Returns(cycleInfo.Object); + cycleInfo.Setup(c => c.CycleData).Returns( + GetPTOCycleData()); + + runData.DriverData = new DriverData() { + PTODriveRoadsweepingGear = new GearshiftPosition((uint)ptoGear) + }; + //Recreate Shiftstrategy with updated rundata + + var shiftStrategy = GetShiftStrategyAndGearbox(container, out _); + + + var absTime = 0.SI<Second>(); + var dt = 2.SI<Second>(); + + + var expectedN = n_RPM.RPMtoRad(); + var angularVelocity = expectedN / gearRatios[gear]; + + + + + var gearShiftPosition = shiftStrategy.InitGear(0.SI<Second>(), Constants.SimulationSettings.TargetTimeInterval, 1.SI<NewtonMeter>(), + angularVelocity); + + + + var expectedT = tq_Nm.SI<NewtonMeter>(); + var torque = expectedT * gearRatios[gear]; + var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, torque, angularVelocity, expectedT, expectedN, + new GearshiftPosition((uint)gear), -double.MaxValue.SI<Second>(), new ResponseSuccess(this)); + Assert.AreEqual(newGear, shiftStrategy.NextGear.Gear); + Assert.AreEqual(shiftExpected, shiftRequired); + } + + + private MTShiftStrategy GetShiftStrategyAndGearbox(Mock<IVehicleContainer> container, + out Mock<IGearbox> gearbox) + { + gearbox = GetMockGearbox(); + + var shiftStrategy = new MTShiftStrategy(container.Object) { + Gearbox = gearbox.Object + }; + + SetVelocityDropLookupData(shiftStrategy); + return shiftStrategy; + } + + + + private Mock<IVehicleContainer> GetMocks( + double n_RPM, + double[] gearRatios, + out VectoRunData runData, + out Mock<IVehicleInfo> info, + out Mock<ITestPowertrain> testPt, + out Mock<ISimplePowertrainBuilder> ptBuilder) + { + runData = GetRunData(gearRatios); + var container = GetMockVehicleContainer(runData, n_RPM.RPMtoRad(), out info); + + testPt = GetMockTestPowertrain(runData); + + ptBuilder = new Mock<ISimplePowertrainBuilder>(MockBehavior.Strict); + + ptBuilder.Setup(p => p.CreateTestPowertrain(It.IsAny<IVehicleContainer>(),It.IsAny<bool>())) + .Returns(testPt.Object); + + + container.Setup(c => c.SimplePowertrainBuilder).Returns(ptBuilder.Object); + + // gbx = GetMockGearbox(container.Object); + // + // var shiftStrategy = new MTShiftStrategy(container.Object) + // { + // Gearbox = gbx.Object + // }; + // SetVelocityDropLookupData(shiftStrategy); + return container; + } + + + + + private VectoRunData GetRunData(double[] gearRatios) + { + var gearboxData = new GearboxData() { + Gears = new Dictionary<uint, GearData>() + }; + + for (uint i = 1; i < gearRatios.Length; i++) { + var gearRatio = gearRatios[i]; + gearboxData.Gears[i] = new GearData() { + Ratio = gearRatio, + LossMap = TransmissionLossMapReader.Create(0.96, gearRatio, $"Gear {i}") + }; + } + + var gearShiftParameters = new ShiftStrategyParameters() { + StartSpeed = 2.SI<MeterPerSecond>(), + TimeBetweenGearshifts = 6.SI<Second>(), + DownshiftAfterUpshiftDelay = 2.SI<Second>(), + UpshiftAfterDownshiftDelay = 2.SI<Second>(), + UpshiftMinAcceleration = 0.1.SI<MeterPerSquareSecond>() + }; + + + string engineFldHdr = "engine speed [1/min],full load torque [Nm],motoring torque [Nm],PT1 [s]"; + + string[] engineFldData = new[] { + "560,1180,-149,0.6 ", + "600,1282,-148,0.6 ", + "799.9999999,1791,-149,0.6 ", + "1000,2300,-160,0.6 ", + "1200,2300,-179,0.6 ", + "1400,2300,-203,0.6 ", + "1599.999999,2079,-235,0.49", + "1800,1857,-264,0.25 ", + "2000.000001,1352,-301,0.25", + "2100,1100,-320,0.25 ", + }; + + + var fullLoadCurve = + FullLoadCurveReader.Create(InputDataHelper.InputDataAsTableData(engineFldHdr, engineFldData)); + var engineData = new CombustionEngineData() { + IdleSpeed = 560.RPMtoRad(), + FullLoadCurves = new Dictionary<uint, EngineFullLoadCurve>() { + { + 0u, fullLoadCurve + } + } + }; + + + var axlRatio = 3.240355; + var gearsInput = gearboxData.Gears.Select(x => { + var r = new Mock<ITransmissionInputData>(); + r.Setup(g => g.Ratio).Returns(x.Value.Ratio); + return r.Object; + }).ToList(); + foreach (var entry in gearboxData.Gears) { + var gearIdx = (int)entry.Key - 1; + var dynamicTyreRadius = 0.5.SI<Meter>(); + + entry.Value.ShiftPolygon = + DeclarationData.Gearbox.ComputeManualTransmissionShiftPolygon( + gearIdx, engineData.FullLoadCurves.First().Value, + gearsInput, engineData, axlRatio, 0.5.SI<Meter>()); + + entry.Value.ExtendedShiftPolygon = DeclarationData.Gearbox.ComputeManualTransmissionShiftPolygonExtended( + gearIdx, engineData.FullLoadCurves.First().Value, gearsInput, engineData, axlRatio, dynamicTyreRadius); + } + + + var axleGearData = new AxleGearData() { + AxleGear = new TransmissionData() { + Ratio = 3.240355, + } + }; + + + var vehicleData = new VehicleData() { + DynamicTyreRadius = 0.492.SI<Meter>(), + }; + + + var mockCycle = new Mock<IDrivingCycleData>(); + mockCycle.Setup(cd => cd.Entries).Returns( + new List<DrivingCycleData.DrivingCycleEntry>() { + new DrivingCycleData.DrivingCycleEntry() { + RoadGradient = 0.SI<Radian>() + } + }); + + + + return new VectoRunData() { + GearboxData = gearboxData, + GearshiftParameters = gearShiftParameters, + EngineData = engineData, + AxleGearData = axleGearData, + VehicleData = vehicleData, + Cycle = mockCycle.Object, + }; + } + + + private Mock<IGearbox> GetMockGearbox() + { + var mtGbx = new Mock<IMTGearbox>(); + var gbx = mtGbx.As<IGearbox>(); + + gbx.Setup(g => g.LastUpshift).Returns(-double.MaxValue.SI<Second>()); + gbx.Setup(g => g.LastDownshift).Returns(-double.MaxValue.SI<Second>()); + + return gbx; + // var gbx = new Mock<DeclarationData.Gearbox>(container, null); + // var ratios = container.RunData.GearboxData.Gears; + + // + + // gbx.SetupProperty(g => g.Gear); + // gbx.Setup(g => g.Request(It.IsAny<Second>(), It.IsAny<Second>(), It.IsAny<NewtonMeter>(), It.IsAny<PerSecond>(), + // It.IsAny<bool>())) + // .Returns((Second absTime, Second dt, NewtonMeter t, PerSecond n, bool dryRun) => { + // var ratio = gbx.Object.Gear == null ? 1.0 : ratios[gbx.Object.Gear.Gear].Ratio; + // return dryRun + // ? new ResponseDryRun(this) { + // Engine = { + // PowerRequest = n * t, EngineSpeed = n * ratio, + // DynamicFullLoadPower = (t / ratio + 2300.SI<NewtonMeter>()) * n * ratio, + // }, + // Clutch = { PowerRequest = n * t } + // } + // : new ResponseSuccess(this) { + // Engine = { PowerRequest = n * t, EngineSpeed = n * ratio }, + // Clutch = { PowerRequest = n * t } + // }; + // }); + // return gbx; + } + + + private Mock<ITestPowertrainTransmission> GetMockTestGearbox(Dictionary<uint, GearData> ratios) + { + var gbx = new Mock<ITestPowertrainTransmission>(); + + gbx.Setup(g => g.LastUpshift).Returns(-double.MaxValue.SI<Second>()); + gbx.Setup(g => g.LastDownshift).Returns(-double.MaxValue.SI<Second>()); + + GearshiftPosition gear = null; + gbx.SetupGet(g => g.Gear).Returns(() => { + + return gear; + }); + gbx.SetupSet(g => g.SetGear = It.IsAny<GearshiftPosition>()) + .Callback<GearshiftPosition>(p => { + gear = p; + }); + + + GearshiftPosition nextGear = null; + gbx.SetupGet(g => g.NextGear).Returns(() => nextGear); + gbx.SetupSet(g => g.SetNextGear = It.IsAny<GearshiftPosition>()) + .Callback<GearshiftPosition>(p => nextGear = p); + + gbx.Setup(p => p.Initialize(It.IsAny<NewtonMeter>(), + It.IsAny<PerSecond>())).Returns((NewtonMeter tq, PerSecond rpm) => { + return new ResponseSuccess(this) + { + Engine = { + EngineSpeed = rpm, + PowerRequest = tq * rpm, + }, + }; + }); + + + gbx.Setup(g => g.Request(It.IsAny<Second>(), It.IsAny<Second>(), It.IsAny<NewtonMeter>(), It.IsAny<PerSecond>(), + It.IsAny<bool>())) + .Returns((Second absTime, Second dt, NewtonMeter t, PerSecond n, bool dryRun) => { + var ratio = gbx.Object.Gear == null ? 1.0 : ratios[gbx.Object.Gear.Gear].Ratio; + return dryRun + ? new ResponseDryRun(this) { + Engine = { + PowerRequest = n * t, EngineSpeed = n * ratio, + DynamicFullLoadPower = (t / ratio + 2300.SI<NewtonMeter>()) * n * ratio, + }, + Clutch = { PowerRequest = n * t } + } + : new ResponseSuccess(this) { + Engine = { PowerRequest = n * t, EngineSpeed = n * ratio }, + Clutch = { PowerRequest = n * t } + }; + }); + return gbx; + } + private Mock<IPowertainInfo> GetPowertrainInfo() + { + var powerTrainInfo = new Mock<IPowertainInfo>(); + powerTrainInfo.Setup(p => p.HasCombustionEngine).Returns(true); + return powerTrainInfo; + } + + private CycleData GetCycleData() + { + return new CycleData() { + LeftSample = new DrivingCycleData.DrivingCycleEntry() { + PTOActive = PTOActivity.Inactive + } + }; + } + + private CycleData GetPTOCycleData() + { + return new CycleData() { + LeftSample = new DrivingCycleData.DrivingCycleEntry() { + PTOActive = PTOActivity.PTOActivityRoadSweeping + } + }; + } + + private Mock<IVehicleContainer> GetMockVehicleContainer(VectoRunData runData, PerSecond engineSpeed, out Mock<IVehicleInfo> vehicleInfo) + { + var vehicleContainer = new Mock<IVehicleContainer>(); + + var preProcessingRuns = new List<ISimulationPreprocessor>(); + + vehicleContainer.Setup(c => c.RunData).Returns(runData); + vehicleContainer.Setup(c => c.AddComponent(It.IsAny<VectoSimulationComponent>())); + + vehicleContainer.Setup(c => c.AddPreprocessor(It.IsAny<ISimulationPreprocessor>())) + .Callback((ISimulationPreprocessor pre) => preProcessingRuns.Add(pre)); + + //Vehicle Info + vehicleInfo = new Mock<IVehicleInfo>(); + vehicleContainer.Setup(c => c.VehicleInfo).Returns(vehicleInfo.Object); + vehicleInfo.Setup(v => v.VehicleSpeed).Returns(1.KMPHtoMeterPerSecond()); + + vehicleInfo.Setup(v => v.AirDragResistance(It.IsAny<MeterPerSecond>(), It.IsAny<MeterPerSecond>())) + .Returns(0.SI<Newton>()); + vehicleInfo.Setup(v => v.RollingResistance(It.IsAny<Radian>())).Returns(0.SI<Newton>()); + vehicleInfo.Setup(v => v.SlopeResistance(It.IsAny<Radian>())).Returns(0.SI<Newton>()); + vehicleInfo.Setup(v => v.VehicleSpeed).Returns(30.KMPHtoMeterPerSecond()); + vehicleInfo.Setup(v => v.TotalMass).Returns(12000.SI<Kilogram>()); + + //WheelsInfo + vehicleContainer.Setup(c => c.WheelsInfo.ReducedMassWheels).Returns(0.SI<Kilogram>()); + + //AxlegearInfo + var axleGearInfo = new Mock<IAxlegearInfo>(); + vehicleContainer.Setup(c => c.AxlegearInfo).Returns(axleGearInfo.Object); + axleGearInfo.Setup(a => a.AxlegearLoss()).Returns(0.SI<Watt>()); + + //Powertrain Info + vehicleContainer.Setup(c => c.PowertrainInfo).Returns(GetPowertrainInfo().Object); + + //Engine Info + var engineInfo = new Mock<IEngineInfo>(); + vehicleContainer.Setup(c => c.EngineInfo).Returns(engineInfo.Object); + engineInfo.Setup(e => e.EngineIdleSpeed).Returns(runData.EngineData.IdleSpeed); + engineInfo.Setup(e => e.EngineRatedSpeed).Returns(runData.EngineData.FullLoadCurves.First().Value.RatedSpeed); + engineInfo.Setup(e => e.EngineSpeed).Returns(engineSpeed); + engineInfo.Setup(e => e.EngineN95hSpeed).Returns + (runData.EngineData.FullLoadCurves.First().Value.N95hSpeed); + engineInfo.Setup(e => e.EngineStationaryFullPower(It.IsAny<PerSecond>())).Returns((PerSecond n) => + runData.EngineData.FullLoadCurves[0].FullLoadStationaryPower(n)); + + //Cycle Info + var cycleInfo = new Mock<IDrivingCycleInfo>(); + vehicleContainer.Setup(c => c.DrivingCycleInfo).Returns(cycleInfo.Object); + cycleInfo.Setup(c => c.CycleData).Returns( + GetCycleData()); + + cycleInfo.Setup(c => c.CycleLookAhead(It.IsAny<Meter>())).Returns(new DrivingCycleData.DrivingCycleEntry() { + Altitude = 0.SI<Meter>() + }); + cycleInfo.Setup(c => c.Altitude).Returns(0.SI<Meter>()); + + var pi = new Mock<IPowertainInfo>(); + + + + //Driver Info + var driverInfo = new Mock<IDriverInfo>(); + vehicleContainer.Setup(c => c.DriverInfo).Returns(driverInfo.Object); + + driverInfo.Setup(d => d.DriverBehavior).Returns(DrivingBehavior.Accelerating); + driverInfo.Setup(d => d.DrivingAction).Returns(DrivingAction.Accelerate); + + return vehicleContainer; + } + + private Mock<ITestPowertrain> GetMockTestPowertrain(VectoRunData runData) + { + var testPt = new Mock<ITestPowertrain>(MockBehavior.Strict); + var simplePt = GetSimplePowertrain(runData, out var gbx); + + testPt.Setup(c => c.Container).Returns(simplePt.Object); + testPt.Setup(c => c.Gearbox).Returns(gbx.Object); + testPt.Setup(c => c.UpdateComponents()); + + + // var simplePt = GetSimplePowertrain(gearRatios); + // + // + // testContainer.Setup(c => c.RunData).Returns(runData); + // testContainer.Setup(c => c.PowertrainInfo).Returns(GetPowertrainInfo().Object); + // + // testPowertrain.Setup(t => t.Gearbox).Returns(GetMockGearbox(testContainer.Object).Object); + + var tEng = new Mock<ITestpowertrainCombustionEngine>(); + testPt.Setup(t => t.CombustionEngine).Returns(tEng.Object); + tEng.Setup(e => e.EngineStationaryFullPower(It.IsAny<PerSecond>())) + .Returns((PerSecond n) => runData.EngineData.FullLoadCurves[0].FullLoadStationaryPower(n)); + + return testPt; + } + + private Mock<ISimpleVehicleContainer> GetSimplePowertrain(VectoRunData runData, out Mock<ITestPowertrainTransmission> testGearbox) + { + var simplePt = new Mock<ISimpleVehicleContainer>(); + + simplePt.Setup(s => s.RunData).Returns(runData); + simplePt.Setup(s => s.AddComponent(It.IsAny<VectoSimulationComponent>())); + simplePt.Setup(s => s.PowertrainInfo).Returns(GetPowertrainInfo().Object); + + testGearbox = GetMockTestGearbox(runData.GearboxData.Gears); + simplePt.Setup(s => s.GearboxCtl).Returns(testGearbox.Object); + + + //Vehicle Info + var vehicleInfo = new Mock<IVehicleInfo>(); + simplePt.Setup(c => c.VehicleInfo).Returns(vehicleInfo.Object); + vehicleInfo.Setup(v => v.VehicleSpeed).Returns(1.KMPHtoMeterPerSecond()); + + + + + //simplePt.Setup(s => s.AddPreprocessor(It.IsAny<ISimulationPreprocessor>())) + // .Callback((ISimulationPreprocessor p) => p.RunPreprocessing()); + return simplePt; + } + + private void SetVelocityDropLookupData(MTShiftStrategy shiftStrategy) + { + //"StartVelocity [km/h], Gradient [-], EndVelocity [km/h]" + var data = new[] { + new[] { 5.0, -0.0997, 9.061522965237558 }, + new[] { 5.0, -0.0798, 7.76698080079411 }, + new[] { 5.0, -0.0599, 6.46583777913701 }, + new[] { 5.0, -0.0400, 5.1596021788785045 }, + new[] { 5.0, -0.0200, 3.8498121019126907 }, + new[] { 5.0, 0.0000, 2.5380265159468918 }, + new[] { 5.0, 0.0200, 1.2258160477557427 }, + new[] { 5.0, 0.0400, 0.0 }, + new[] { 5.0, 0.0599, 0.0 }, + new[] { 5.0, 0.0798, 0.0 }, + new[] { 5.0, 0.0997, 0.0 }, + new[] { 10.0, -0.0997, 14.807789640888302 }, + new[] { 10.0, -0.0798, 13.474253785811362 }, + new[] { 10.0, -0.0599, 12.133880027250777 }, + new[] { 10.0, -0.0400, 10.788221550084467 }, + new[] { 10.0, -0.0200, 9.438862432338068 }, + new[] { 10.0, 0.0000, 8.087408432114643 }, + new[] { 10.0, 0.0200, 6.735477499784416 }, + new[] { 10.0, 0.0400, 5.384690105076845 }, + new[] { 10.0, 0.0599, 4.036659549786269 }, + new[] { 10.0, 0.0798, 2.6929823705748137 }, + new[] { 10.0, 0.0997, 1.3552289800549435 }, + new[] { 20.0, -0.0997, 25.061542153872097 }, + new[] { 20.0, -0.0798, 23.72002987685605 }, + new[] { 20.0, -0.0599, 22.371630788642932 }, + new[] { 20.0, -0.0400, 21.017907257116025 }, + new[] { 20.0, -0.0200, 19.660452757813403 }, + new[] { 20.0, 0.0000, 18.30088261992287 }, + new[] { 20.0, 0.0200, 16.94082447048767 }, + new[] { 20.0, 0.0400, 15.581908518759507 }, + new[] { 20.0, 0.0599, 14.225757795590708 }, + new[] { 20.0, 0.0798, 12.873978508374211 }, + new[] { 20.0, 0.0997, 11.528150617530041 }, + new[] { 30.000000000000004, -0.0997, 35.091774208140095 }, + new[] { 30.000000000000004, -0.0798, 33.750904327320896 }, + new[] { 30.000000000000004, -0.0599, 32.40315158162777 }, + new[] { 30.000000000000004, -0.0400, 31.050077596965064 }, + new[] { 30.000000000000004, -0.0200, 29.69327509188113 }, + new[] { 30.000000000000004, 0.0000, 28.33435862498606 }, + new[] { 30.000000000000004, 0.0200, 26.974955046566407 }, + new[] { 30.000000000000004, 0.0400, 25.616693776603913 }, + new[] { 30.000000000000004, 0.0599, 24.261197065863925 }, + new[] { 30.000000000000004, 0.0798, 22.91007034016412 }, + new[] { 30.000000000000004, 0.0997, 21.56489279686667 }, + new[] { 40.0, -0.0997, 45.024018797189854 }, + new[] { 40.0, -0.0798, 43.68636622428101 }, + new[] { 40.0, -0.0599, 42.34185052441486 }, + new[] { 40.0, -0.0400, 40.99202962224952 }, + new[] { 40.0, -0.0200, 39.63849244500093 }, + new[] { 40.0, 0.0000, 38.282849690992855 }, + new[] { 40.0, 0.0200, 36.926724305651554 }, + new[] { 40.0, 0.0400, 35.57174178507285 }, + new[] { 40.0, 0.0599, 34.21952045137207 }, + new[] { 40.0, 0.0798, 32.87166183129923 }, + new[] { 40.0, 0.0997, 31.5297412694979 }, + new[] { 50.0, -0.0997, 54.652157586769704 }, + new[] { 50.0, -0.0798, 53.319266704395716 }, + new[] { 50.0, -0.0599, 51.97954186606304 }, + new[] { 50.0, -0.0400, 50.634535516787736 }, + new[] { 50.0, -0.0200, 49.28583097196263 }, + new[] { 50.0, 0.0000, 47.93503321632867 }, + new[] { 50.0, 0.0200, 46.583759417454765 }, + new[] { 50.0, 0.0400, 45.23362925944123 }, + new[] { 50.0, 0.0599, 43.88625525588574 }, + new[] { 50.0, 0.0798, 42.54323315977748 }, + new[] { 50.0, 0.0997, 41.20613261641401 }, + new[] { 60.00000000000001, -0.0997, 64.2503607025971 }, + new[] { 60.00000000000001, -0.0798, 62.91932863058169 }, + new[] { 60.00000000000001, -0.0599, 61.58156853535776 }, + new[] { 60.00000000000001, -0.0400, 60.23862904729555 }, + new[] { 60.00000000000001, -0.0200, 58.89369896300112 }, + new[] { 60.00000000000001, 0.0000, 57.547040626925885 }, + new[] { 60.00000000000001, 0.0200, 56.199911833784675 }, + new[] { 60.00000000000001, 0.0400, 54.85392730356455 }, + new[] { 60.00000000000001, 0.0599, 53.510694584916905 }, + new[] { 60.00000000000001, 0.0798, 52.17180450267632 }, + new[] { 60.00000000000001, 0.0997, 50.83882182989668 }, + new[] { 70.0, -0.0997, 73.78388063954164 }, + new[] { 70.0, -0.0798, 72.45700102808648 }, + new[] { 70.0, -0.0599, 71.12341092304165 }, + new[] { 70.0, -0.0400, 69.78459543842656 }, + new[] { 70.0, -0.0200, 68.44188526693415 }, + new[] { 70.0, 0.0000, 67.09719334997524 }, + new[] { 70.0, 0.0200, 65.75212749798493 }, + new[] { 70.0, 0.0400, 64.40829754257321 }, + new[] { 70.0, 0.0599, 63.06730571969745 }, + new[] { 70.0, 0.0798, 61.73073716025881 }, + new[] { 70.0, 0.0997, 60.40015062055851 }, + new[] { 80.0, -0.0997, 83.25457689135129 }, + new[] { 80.0, -0.0798, 81.93182852399568 }, + new[] { 80.0, -0.0599, 80.60238880559001 }, + new[] { 80.0, -0.0400, 79.2676325992058 }, + new[] { 80.0, -0.0200, 77.92916666616652 }, + new[] { 80.0, 0.0000, 76.58872134590663 }, + new[] { 80.0, 0.0200, 75.24790011046437 }, + new[] { 80.0, 0.0400, 73.90830846424944 }, + new[] { 80.0, 0.0599, 72.57154434889891 }, + new[] { 80.0, 0.0798, 71.23918865436896 }, + new[] { 80.0, 0.0997, 69.91277394305271 }, + }; + var entries = new List<VelocitySpeedGearshiftPreprocessor.Entry>(); + foreach (var d in data) { + entries.Add(new VelocitySpeedGearshiftPreprocessor.Entry() { + StartVelocity = d[0].KMPHtoMeterPerSecond(), + Gradient = d[1].SI<Radian>(), + EndVelocity = d[2].KMPHtoMeterPerSecond(), + }); + } + + shiftStrategy.VelocityDropData.Data = entries.ToArray(); + + } +} \ No newline at end of file diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Shiftstrategies/MTShiftStrategy.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Shiftstrategies/MTShiftStrategy.cs index c013c4943c..78aafdcb9c 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Shiftstrategies/MTShiftStrategy.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Shiftstrategies/MTShiftStrategy.cs @@ -53,10 +53,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies protected GearshiftPosition DesiredGearRoadsweeping; - protected MTGearbox _gearbox; + protected IMTGearbox _gearbox; public MTShiftStrategy(IVehicleContainer container) : base(container) { + // create testcontainer + TestPowertrain = PowertrainBuilder.CreateTestPowertrain(Container, false); PreprocessorSpeed = ConfigureSpeedPreprocessor(container); container.AddPreprocessor(PreprocessorSpeed); @@ -81,8 +83,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies } } - // create testcontainer - TestPowertrain = PowertrainBuilder.CreateTestPowertrain(Container, false); + DesiredGearRoadsweeping = RunData.DriverData?.PTODriveRoadsweepingGear; } @@ -90,7 +91,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies public override IGearbox Gearbox { get => _gearbox; set { - if (value is MTGearbox gbx) { + if (value is IMTGearbox gbx) { _gearbox = gbx; return; } @@ -200,10 +201,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies while (currentGear.Gear < GearboxModelData.Gears.Count) { currentGear = Gears.Successor(currentGear); - var tmpGear = Gearbox.Gear; - _gearbox.Gear = currentGear; - var response = (ResponseDryRun)_gearbox.Request(absTime, dt, outTorque, outAngularVelocity, true); - _gearbox.Gear = tmpGear; + var response = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, currentGear); inAngularVelocity = response.Engine.EngineSpeed; //ModelData.Gears[currentGear].Ratio * outAngularVelocity; inTorque = response.Clutch.PowerRequest / inAngularVelocity; @@ -226,6 +224,20 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies return currentGear; } + private ResponseDryRun RequestDryRunWithGear(Second absTime, Second dt, NewtonMeter outTorque, + PerSecond outAngularVelocity, GearshiftPosition currentGear) + { + TestPowertrain.UpdateComponents(); + var testGearbox = TestPowertrain.Gearbox; + var tmpGear = testGearbox.Gear; + // _gearbox.Gear = currentGear; + testGearbox.SetGear = currentGear; + // _gearbox.Gear = tmpGear; + testGearbox.SetGear = tmpGear; + var response = (ResponseDryRun)testGearbox.Request(absTime, dt, outTorque, outAngularVelocity, true); + return response; + } + protected virtual GearshiftPosition DoCheckDownshift(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, NewtonMeter inTorque, PerSecond inAngularVelocity, GearshiftPosition currentGear, IResponse response1) { @@ -243,10 +255,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies currentGear = Gears.Predecessor(currentGear); while (currentGear.Gear > 1) { currentGear = Gears.Predecessor(currentGear); - var tmpGear = Gearbox.Gear; - _gearbox.Gear = currentGear; - var response = (ResponseDryRun)_gearbox.Request(absTime, dt, outTorque, outAngularVelocity, true); - _gearbox.Gear = tmpGear; + var response = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, currentGear); + // var tmpGear = Gearbox.Gear; + // _gearbox.Gear = currentGear; + // var response = (ResponseDryRun)_gearbox.Request(absTime, dt, outTorque, outAngularVelocity, true); + // _gearbox.Gear = tmpGear; inAngularVelocity = GearboxModelData.Gears[currentGear.Gear].Ratio * outAngularVelocity; inTorque = response.Clutch.PowerRequest / inAngularVelocity; -- GitLab From 11b352dcf1a0f82a800975acba8ff67b20532c20 Mon Sep 17 00:00:00 2001 From: "VKMTHD\\haraldmartini" <martini@ivt.tugraz.at> Date: Sun, 16 Mar 2025 14:41:30 +0100 Subject: [PATCH 12/22] Added ATShiftStrategyOptimizedTests.cs --- .../AMTShiftStrategyOptimizedTests.cs | 22 - .../ATShiftStrategyOptimizedTests.cs | 1565 +++++++++++++++++ 2 files changed, 1565 insertions(+), 22 deletions(-) create mode 100644 Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyOptimizedTests.cs diff --git a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/AMTShiftStrategyOptimizedTests.cs b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/AMTShiftStrategyOptimizedTests.cs index 5e72e31099..886a5e6340 100644 --- a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/AMTShiftStrategyOptimizedTests.cs +++ b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/AMTShiftStrategyOptimizedTests.cs @@ -523,31 +523,9 @@ TestCase(8, 4, 15000, 200, true),] { var shiftStrategy = new AMTShiftStrategyOptimized(vehicleContainer.Object); - gbx = GetMockGearbox(); - var mockPort = new Mock<ITnOutPort>(); shiftStrategy.Gearbox = gbx.Object; - - // NewtonMeter tqRequest = null; - // PerSecond rpmRequest = null; - // mockPort.Setup(p => p.Initialize(It.IsAny<NewtonMeter>(), - // It.IsAny<PerSecond>())).Returns((NewtonMeter tq, PerSecond rpm) => { - // tqRequest = tq; - // rpmRequest = rpm; - // return new ResponseSuccess(this) - // { - // Engine = { - // EngineSpeed = rpm, - // PowerRequest = tq * rpm, - // }, - // }; - // }); - // mockPort.Setup(p => p.Request(It.IsAny<Second>(), It.IsAny<Second>(), It.IsAny<NewtonMeter>(), - // It.IsAny<PerSecond>(), true)).Returns(new ResponseDryRun(this)); - // - // gbx.Connect(mockPort.Object); - SetVelocityDropLookupData(shiftStrategy); return shiftStrategy; } diff --git a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyOptimizedTests.cs b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyOptimizedTests.cs new file mode 100644 index 0000000000..8e2fa264ae --- /dev/null +++ b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyOptimizedTests.cs @@ -0,0 +1,1565 @@ +using System.ComponentModel; +using System.Globalization; +using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; +using System.Security.Cryptography; +using Moq; +using NUnit.Framework; +using NUnit.Framework.Internal; +using TUGraz.Vecto.UnitTests.Utils.MockComponents; +using TUGraz.VectoCommon.BusAuxiliaries; +using TUGraz.VectoCommon.InputData; +using TUGraz.VectoCommon.Models; +using TUGraz.VectoCommon.Utils; +using TUGraz.VectoCore.Configuration; +using TUGraz.VectoCore.InputData.Reader.ComponentData; +using TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.SimulationComponents; +using TUGraz.VectoCore.Models.Connector.Ports; +using TUGraz.VectoCore.Models.Connector.Ports.Impl; +using TUGraz.VectoCore.Models.Declaration; +using TUGraz.VectoCore.Models.Simulation; +using TUGraz.VectoCore.Models.Simulation.Data; +using TUGraz.VectoCore.Models.Simulation.DataBus; +using TUGraz.VectoCore.Models.Simulation.Impl; +using TUGraz.VectoCore.Models.SimulationComponent; +using TUGraz.VectoCore.Models.SimulationComponent.Data; +using TUGraz.VectoCore.Models.SimulationComponent.Data.Engine; +using TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox; +using TUGraz.VectoCore.Models.SimulationComponent.Impl; +using TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies; +using TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies.ShiftPolygonCalc; +using TUGraz.VectoCore.OutputData.XML.DeclarationReports.ManufacturerReport.ManufacturerReport_0_9.ManufacturerReportGroupWriter; +using TUGraz.VectoCore.Tests.Utils; +using Assert = NUnit.Framework.Assert; + +namespace TUGraz.Vecto.UnitTests.TestCases.Components.GearShiftStrategy; + +[TestFixture] +public class ATShiftStrategyOptimizedTests +{ + [TestCase(0, 100, 1)] + [TestCase(0, 200, 1)] + [TestCase(5, 100, 1)] + [TestCase(5, 300, 1)] + [TestCase(5, 600, 1)] + [TestCase(15, 100, 3)] + [TestCase(15, 300, 3)] + [TestCase(15, 600, 3)] + [TestCase(40, 100, 6)] + [TestCase(40, 300, 6)] + [TestCase(40, 600, 6)] + [TestCase(70, 100, 6)] + [TestCase(70, 300, 6)] + [TestCase(70, 600, 6)] + public void TestATGearInitialize(double vehicleSpeed, double torque, int expectedGear) + { + var gearRatios = new[] { 3.4, 1.9, 1.42, 1.0, 0.7, 0.62 }; + var vehicleContainer = GetMockVehicleContainer( + speedKmh: vehicleSpeed, + DrivingBehavior.Accelerating, + gearRatios, + out _, + out var runData, + out _, + out _); + + var shiftStrategy = new ATShiftStrategyOptimized(vehicleContainer.Object); + var angularVelocity = GetAngularVelocityBySpeed(vehicleSpeed, runData); + var response = shiftStrategy.InitGear( + 0.SI<Second>(), + 1.SI<Second>(), + torque.SI<NewtonMeter>(), + angularVelocity); + + Assert.AreEqual(expectedGear, response.Gear); + } + private Mock<IVehicleContainer> GetMockVehicleContainer(double speedKmh, DrivingBehavior driverBehavior, + double[] gearRatios, + out Mock<IVehicleDeclarationInputData> inputData, out VectoRunData runData, out GearboxData gearboxData, + out Mock<ISimpleVehicleContainer> simplePt) + { + var vehicleContainer = new Mock<IVehicleContainer>(); + + inputData = GetMockInputData(gearRatios); + runData = GetDummyVectoRunData(inputData.Object); + + + + vehicleContainer.Setup(c => c.RunData).Returns(runData); + + //Testpowertrain + var testPowertrain = GetMockTestPowertrain( + runData, + out simplePt); + + vehicleContainer.Setup(c => c.SimplePowertrainBuilder.CreateTestPowertrain(It.IsAny<IVehicleContainer>(), + It.IsAny<bool>())).Returns(testPowertrain.Object); + + //VehicleInfo + vehicleContainer.Setup(v => v.VehicleInfo) + .Returns(GetVehicleInfo(speedKmh.KMPHtoMeterPerSecond()).Object); + + //AxleGearInfo + var axleGearInfo = new Mock<IAxlegearInfo>(); + vehicleContainer.Setup(c => c.AxlegearInfo).Returns(axleGearInfo.Object); + axleGearInfo.Setup(a => a.AxlegearLoss()).Returns(0.SI<Watt>()); + + //WheelsInfo + var wi = new Mock<IWheelsInfo>(); + vehicleContainer.Setup(c => c.WheelsInfo).Returns(wi.Object); + wi.Setup(w => w.ReducedMassWheels).Returns(0.SI<Kilogram>()); + + //Cycle Info + var cycleInfo = new Mock<IDrivingCycleInfo>(); + vehicleContainer.Setup(c => c.DrivingCycleInfo).Returns(cycleInfo.Object); + cycleInfo.Setup(c => c.CycleData).Returns( + GetCycleData()); + cycleInfo.Setup(c => c.RoadGradient).Returns(0.SI<Radian>()); + + + cycleInfo.Setup(c => c.CycleLookAhead(It.IsAny<Meter>())).Returns(new DrivingCycleData.DrivingCycleEntry() + { + Altitude = 0.SI<Meter>() + }); + cycleInfo.Setup(c => c.Altitude).Returns(0.SI<Meter>()); + + //DriverINfo + vehicleContainer.Setup(v => v.DriverInfo.DriverBehavior).Returns(driverBehavior); + var acc = 0.SI<MeterPerSquareSecond>(); + switch (driverBehavior) + { + case DrivingBehavior.Accelerating: + acc = 1.SI<MeterPerSquareSecond>(); + break; + case DrivingBehavior.Braking: + acc = -1.SI<MeterPerSquareSecond>(); + break; + case DrivingBehavior.Halted: + acc = 0.SI<MeterPerSquareSecond>(); + break; + default: + throw new ArgumentOutOfRangeException(); + } + + + + + + vehicleContainer.Setup(v => v.DriverInfo.DriverAcceleration).Returns(acc); + gearboxData = new GearboxData(); + return vehicleContainer; + } + private CycleData GetCycleData() + { + return new CycleData() + { + LeftSample = new DrivingCycleData.DrivingCycleEntry() + { + PTOActive = PTOActivity.Inactive, + VehicleTargetSpeed = 10.KMPHtoMeterPerSecond() + } + }; + } + private Mock<IVehicleInfo> GetVehicleInfo(MeterPerSecond speed) + { + var vehicleInfo = new Mock<IVehicleInfo>(); + vehicleInfo.Setup(v => v.VehicleSpeed).Returns(speed); + vehicleInfo.Setup(v => v.AirDragResistance(It.IsAny<MeterPerSecond>(), It.IsAny<MeterPerSecond>())) + .Returns(0.SI<Newton>()); + vehicleInfo.Setup(v => v.RollingResistance(It.IsAny<Radian>())).Returns(0.SI<Newton>()); + vehicleInfo.Setup(v => v.SlopeResistance(It.IsAny<Radian>())).Returns(0.SI<Newton>()); + vehicleInfo.Setup(v => v.TotalMass).Returns(12000.SI<Kilogram>()); + return vehicleInfo; + } + private Mock<ITestPowertrain> GetMockTestPowertrain(VectoRunData runData, + out Mock<ISimpleVehicleContainer> simpleContainer) + { + var testPt = new Mock<ITestPowertrain>(); + simpleContainer = GetSimplePowertrain(runData, + out var testGearbox); + + + + testPt.Setup(t => t.Container).Returns(simpleContainer.Object); + testPt.Setup(t => t.Gearbox).Returns(testGearbox.Object); + + + //Vehicle + var vehicle = new Mock<ITestPowertrainVehicle>(); + vehicle.Setup(v => v.Initialize( + It.IsAny<MeterPerSecond>(), + It.IsAny<Radian>())).Returns(new ResponseSuccess(this)); + testPt.Setup(t => t.Vehicle).Returns(vehicle.Object); + + + return testPt; + } + private Mock<IVehicleDeclarationInputData> GetMockInputData(double[]? gearRatios) + { + var input = new Mock<IVehicleDeclarationInputData>(); + var components = new Mock<IVehicleComponentsDeclaration>(); + input.Setup(i => i.Components).Returns(components.Object); + var gbx = new Mock<IGearboxDeclarationInputData>(); + var tc = new Mock<ITorqueConverterDeclarationInputData>(); + + components.Setup(c => c.GearboxInputData).Returns(gbx.Object); + components.Setup(c => c.TorqueConverterInputData).Returns(tc.Object); + gearRatios = gearRatios ?? new double[] { + + }; + var header = "Input Speed [rpm],Input Torque [Nm],Torque Loss [Nm]"; + var efficiency = 0.98; + var data = new List<string>(); + + foreach (var speed in new[] {0, 10000}) { + foreach (var tq in new[] {1e5, -1e5, 0}) { + data.Add(FormattableString.Invariant($"{speed:f2}, {tq:f2}, {(1 - efficiency) * Math.Abs(tq)}")); + } + } + var lossmap = InputDataHelper.InputDataAsTableData(header, data.ToArray()); + //lossmap.Columns + var gears = gearRatios.Select((x, idx) => { + var gear = new Mock<ITransmissionInputData>(); + gear.Setup(g => g.Ratio).Returns(x); + gear.Setup(g => g.Gear).Returns(idx + 1); + //gear.Setup(g => g.Efficiency).Returns(0.98); + gear.Setup(g => g.LossMap).Returns(lossmap); + gear.Setup(g => g.MaxInputSpeed).Returns(2000.RPMtoRad()); + return gear.Object; + }).ToList(); + gbx.Setup(g => g.Type).Returns(GearboxType.ATSerial); + gbx.Setup(g => g.Gears).Returns(gears); + + var tcData = InputDataHelper.InputDataAsTableData(TcHeader, TcData); + tc.Setup(t => t.TCData).Returns(tcData); + return input; + } + private static VectoRunData GetDummyVectoRunData(IVehicleDeclarationInputData inputData) + { + var nrOfGears = inputData.Components.GearboxInputData.Gears.Count; + var fldData = InputDataHelper.InputDataAsTableData(EngineFldHeader, EngineFldData); + var fld = FullLoadCurveReader.Create(fldData); + + // create gearbox data + var tcDataAdapter = new TorqueConverterDataAdapter(); + + // fuel data + var fuelData = new CombustionEngineFuelData() { + ConsumptionMap = FuelConsumptionMapReader.Create( + InputDataHelper.InputDataAsTableData( + "engine speed [rpm] ,torque [Nm] ,fuel consumption [g/h] ,whr power electrical [W]", + "500,-131,0,0", + "500,95.6,1814.959,0", + "500,573.6,9771.095,0", + "2453,-209.12,0,0", + "2453,764.8,39097.94,0" + )), + FuelData = DeclarationData.FuelData.Lookup(FuelType.DieselCI), + }; + + var runData = new VectoRunData() { + VehicleData = new VehicleData() { + DynamicTyreRadius = 0.465.SI<Meter>(), + GrossVehicleMass = 12_000.SI<Kilogram>(), + CurbMass = 10_000.SI<Kilogram>(), + }, + EngineData = new CombustionEngineData() { + Inertia = 0.SI<KilogramSquareMeter>(), + FullLoadCurves = new Dictionary<uint, EngineFullLoadCurve>(), + IdleSpeed = 600.RPMtoRad(), + RatedSpeedDeclared = 2000.RPMtoRad(), + Fuels = new List<CombustionEngineFuelData>() { + fuelData, + } + }, + Cycle = new DrivingCycleData() { + CycleType = CycleType.DistanceBased + } + }; + for (uint i = 0; i <= nrOfGears; i++) { + runData.EngineData.FullLoadCurves[i] = fld; + } + + var gbxDataAdapter = new GearboxDataAdapter(tcDataAdapter); + var gbxTypes = new[] { + GearboxType.ATSerial, GearboxType.ATPowerSplit + }; + + var gearboxData = gbxDataAdapter.CreateGearboxData(inputData, runData, new ATShiftStrategyOptimizedPolygonCalculator(), new GearboxType[] { + GearboxType.ATSerial, + GearboxType.ATPowerSplit + }); + + var gearShiftParams = + gbxDataAdapter.CreateGearshiftData(1.0, runData.EngineData.IdleSpeed, GearboxType.ATSerial, nrOfGears); + + runData.GearboxData = gearboxData; + runData.GearshiftParameters = gearShiftParams; + return runData; + } + private Mock<ISimpleVehicleContainer> GetSimplePowertrain(VectoRunData runData, out Mock<ITestPowertrainTransmission> testGearbox) + { + var simplePt = new Mock<ISimpleVehicleContainer>(); + + testGearbox = GetMockTestGearbox(runData.GearboxData.Gears); + + + simplePt.Setup(s => s.GearboxInfo).Returns(testGearbox.Object); + + + + + + //VehiclePort + return simplePt; + } + private Mock<ITestPowertrainTransmission> GetMockTestGearbox(Dictionary<uint, GearData> ratios) + { + Mock<IAPTGearbox> amtGearbox = new Mock<IAPTGearbox>(); + amtGearbox.Name = "APT_TestGearbox"; + Mock<ITestPowertrainTransmission> gbx = amtGearbox.As<ITestPowertrainTransmission>(); + + + + gbx.Setup(g => g.LastUpshift).Returns(-double.MaxValue.SI<Second>()); + gbx.Setup(g => g.LastDownshift).Returns(-double.MaxValue.SI<Second>()); + + GearshiftPosition gear = null; + gbx.SetupGet(g => g.Gear).Returns(() => { + + return gear; + }); + gbx.SetupSet(g => g.SetGear = It.IsAny<GearshiftPosition>()) + .Callback<GearshiftPosition>(p => { + gear = p; + }); + + + GearshiftPosition nextGear = null; + gbx.SetupGet(g => g.NextGear).Returns(() => nextGear); + gbx.SetupSet(g => g.SetNextGear = It.IsAny<GearshiftPosition>()) + .Callback<GearshiftPosition>(p => nextGear = p); + + gbx.Setup(p => p.Initialize(It.IsAny<NewtonMeter>(), + It.IsAny<PerSecond>())).Returns((NewtonMeter tq, PerSecond rpm) => { + return new ResponseSuccess(this) + { + Engine = { + EngineSpeed = rpm, + PowerRequest = tq * rpm, + }, + }; + }); + gbx.Setup(p => p.Request( + It.IsAny<Second>(), + It.IsAny<Second>(), + It.IsAny<NewtonMeter>(), + It.IsAny<PerSecond>(), + true)).Returns(( + Second absTime, + Second dt, + NewtonMeter t, + PerSecond n, + bool dryRun) => { + + var ratio = + gbx.Object.Gear == null ? 1.0 : ratios[gbx.Object.Gear.Gear].Ratio; + return dryRun + ? new ResponseDryRun(this) { + Engine = { + PowerRequest = n * t, EngineSpeed = n * ratio, + DynamicFullLoadPower = (t / ratio + 2300.SI<NewtonMeter>()) * n * ratio, + TotalTorqueDemand = t, + }, + Clutch = { PowerRequest = n * t }, + DeltaFullLoad = n * t / 2 * (-1) + } + : new ResponseSuccess(this) { + Engine = { + PowerRequest = n * t, + EngineSpeed = n * ratio + + }, + Clutch = { PowerRequest = n * t } + }; + }); + return gbx; + } + + private Mock<IAPTGearbox> GetGearbox(Dictionary<uint, GearData> ratios) + { + + Mock<IAPTGearbox> amtGearbox = new Mock<IAPTGearbox>(); + amtGearbox.Name = "APT_Gearbox"; + + var gbx = amtGearbox.As<IAPTGearbox>(); + // Mock<ITestPowertrainTransmission> gbx = amtGearbox.As<ITestPowertrainTransmission>(); + + + + + // gbx.Setup(g => g.LastUpshift).Returns(-double.MaxValue.SI<Second>()); + // gbx.Setup(g => g.LastDownshift).Returns(-double.MaxValue.SI<Second>()); + // + // GearshiftPosition gear = null; + // gbx.SetupGet(g => g.Gear).Returns(() => { + // + // return gear; + // }); + // gbx.SetupSet(g => g.SetGear = It.IsAny<GearshiftPosition>()) + // .Callback<GearshiftPosition>(p => { + // gear = p; + // }); + + + // GearshiftPosition nextGear = null; + // gbx.SetupGet(g => g.NextGear).Returns(() => nextGear); + // gbx.SetupSet(g => g.SetNextGear = It.IsAny<GearshiftPosition>()) + // .Callback<GearshiftPosition>(p => nextGear = p); + // + // gbx.Setup(p => p.Initialize(It.IsAny<NewtonMeter>(), + // It.IsAny<PerSecond>())).Returns((NewtonMeter tq, PerSecond rpm) => { + // return new ResponseSuccess(this) + // { + // Engine = { + // EngineSpeed = rpm, + // PowerRequest = tq * rpm, + // }, + // }; + // }); + // gbx.Setup(p => p.Request( + // It.IsAny<Second>(), + // It.IsAny<Second>(), + // It.IsAny<NewtonMeter>(), + // It.IsAny<PerSecond>(), + // true)).Returns(( + // Second absTime, + // Second dt, + // NewtonMeter t, + // PerSecond n, + // bool dryRun) => { + // + // var ratio = + // gbx.Object.Gear == null ? 1.0 : ratios[gbx.Object.Gear.Gear].Ratio; + // return dryRun + // ? new ResponseDryRun(this) { + // Engine = { + // PowerRequest = n * t, EngineSpeed = n * ratio, + // DynamicFullLoadPower = (t / ratio + 2300.SI<NewtonMeter>()) * n * ratio, + // TotalTorqueDemand = t, + // }, + // Clutch = { PowerRequest = n * t }, + // DeltaFullLoad = n * t / 2 * (-1) + // } + // : new ResponseSuccess(this) { + // Engine = { + // PowerRequest = n * t, + // EngineSpeed = n * ratio + // + // }, + // Clutch = { PowerRequest = n * t } + // }; + // }); + + return gbx; + } + private static PerSecond GetAngularVelocityBySpeed(double speedKmh, VectoRunData runData) + { + // r_dyn = 0.465m, i_axle = 6.2 + var angularVelocity = + speedKmh.KMPHtoMeterPerSecond() + / runData.VehicleData.DynamicTyreRadius * 6.2; + return angularVelocity; + } + + + + + + + public const string TcHeader = "Speed Ratio, Torque Ratio,MP1000"; + + public static readonly string[] TcData = new[] { + "0.0,1.80,377.80", + "0.1,1.71,365.21", + "0.2,1.61,352.62", + "0.3,1.52,340.02", + "0.4,1.42,327.43", + "0.5,1.33,314.84", + "0.6,1.23,302.24", + "0.7,1.14,264.46", + "0.8,1.04,226.68", + "0.9,1.02,188.90", + "1.0,1.0,0.00", + "1.100,0.999,-40.34", + "1.222,0.998,-80.34", + "1.375,0.997,-136.11", + "1.571,0.996,-216.52", + "1.833,0.995,-335.19", + "2.200,0.994,-528.77", + "2.750,0.993,-883.40", + "4.400,0.992,-2462.17", + "11.000,0.991,-16540.98", + }; + + public const string EngineFldHeader = "engine speed [1/min],full load torque [Nm],motoring torque [Nm],PT1 [s]"; + + public static readonly string[] EngineFldData = new[] { + "560,1180,-149,0.6", + "600,1282,-148,0.6", + "799.9999999,1791,-149,0.6", + "1000,2300,-160,0.6", + "1200,2300,-179,0.6", + "1400,2300,-203,0.6", + "1599.999999,2079,-235,0.49", + "1800,1857,-264,0.25", + "2000.000001,1352,-301,0.25", + "2100,1100,-320,0.25", + }; + + + + + + + + + + + + + + + + + + + + + +} + +// public void TestATGearInitialize(double vehicleSpeed, double torque, int expectedGear) +// { +// var gearRatios = new[] { 3.4, 1.9, 1.42, 1.0, 0.7, 0.62 }; +// +// var gbxTypes = new[] { +// GearboxType.ATSerial +// }; +// +// var vehicleContainer = GetMockVehicleContainer( +// vehicleSpeed, +// DrivingBehavior.Accelerating, +// gearRatios, +// out var inputData, +// out var runData, +// out var gearboxData, out _); +// +// var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); +// +// var angularVelocity = GetAngularVelocityBySpeed(vehicleSpeed, runData); +// var response = gbx.Initialize(torque.SI<NewtonMeter>(), angularVelocity); +// +// Assert.IsInstanceOf(typeof(ResponseSuccess), response); +// Assert.AreEqual(expectedGear, gbx.Gear.Gear); +// Assert.AreEqual(vehicleSpeed.IsEqual(0), gbx.Disengaged); +// } +// +// +// [TestCase(1, 1, 1000, 1500, 0, Description = "Engage 0-> 1C")] +// public void Gearbox_Engage(int gear, int newGear, double tqNm, double nRPM, double speedKmh) +// { +// var gearRatios = new[] { 6.38, 4.63, 3.44, 2.59, 1.86, 1.35, 1, 0.76 }; +// +// var vehicleContainer = GetMockVehicleContainer(speedKmh, DrivingBehavior.Accelerating, gearRatios, +// inputData: out _, +// runData: out var runData, +// gearboxData: out _, simplePt: out _); +// +// var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); +// var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData: runData); +// +// var response = gbx.Initialize(0.SI<NewtonMeter>(), angularVelocity); +// +// +// +// var absTime = 0.SI<Second>(); +// var dt = 2.SI<Second>(); +// +// +// var expectedN = nRPM.RPMtoRad(); +// angularVelocity = expectedN / gearRatios[gear]; +// +// +// gbx.CurrentState = new ATGearbox.ATGearboxState() +// { +// Gear = gbx.Gear, +// }; +// +// var expectedT = tqNm.SI<NewtonMeter>(); +// var torque = expectedT * gearRatios[gear]; +// +// var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, torque, angularVelocity, expectedT, expectedN, +// new GearshiftPosition((uint)gear), -double.MaxValue.SI<Second>(), new ResponseSuccess(this)); +// +// Assert.AreEqual(newGear, shiftStrategy.NextGear.Gear); +// +// var shiftExpected = gear != newGear; //Different Gear +// shiftExpected = shiftRequired || gbx.Disengaged; //Gearbox was disengaged +// +// Assert.AreEqual(shiftExpected, shiftRequired); +// } +// +// [TestCase(2, 1, -1000, 1500, 4, DrivingBehavior.Braking, Description = "_ -> 0: disengage before halting")] +// public void Gearbox_Disengange(int gear, int newGear, double tqNm, double nRPM, double speedKmh, +// DrivingBehavior driverBehavior) +// { +// var gearRatios = new[] { 6.38, 4.63, 3.44, 2.59, 1.86, 1.35, 1, 0.76 }; +// +// var vehicleContainer = GetMockVehicleContainer(speedKmh, +// driverBehavior, +// gearRatios, +// out var inputData, +// out var runData, +// out var gearboxData, out _); +// +// var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); +// var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); +// +// gbx.Initialize(0.SI<NewtonMeter>(), angularVelocity); +// +// +// var absTime = 0.SI<Second>(); +// var dt = 2.SI<Second>(); +// +// +// var expectedN = nRPM.RPMtoRad(); +// angularVelocity = expectedN / gearRatios[gear]; +// +// //Called in gbx initialize +// //var gearShiftPosition = shiftStrategy.InitGear(absTime, Constants.SimulationSettings.TargetTimeInterval, 1.SI<NewtonMeter>(), +// // angularVelocity); +// var engagedPosition = shiftStrategy.Engage(absTime, dt, null, null); +// +// +// Assert.IsTrue(engagedPosition.Engaged); +// +// gbx.CurrentState = new ATGearbox.ATGearboxState() +// { +// Disengaged = gbx.Disengaged, +// Gear = gbx.Gear, +// }; +// +// var expectedT = tqNm.SI<NewtonMeter>(); +// var torque = expectedT * gearRatios[gear]; +// +// +// var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, torque, angularVelocity, expectedT, expectedN, +// new GearshiftPosition((uint)gear), -double.MaxValue.SI<Second>(), new ResponseSuccess(this)); +// +// Assert.AreEqual(newGear, shiftStrategy.NextGear.Gear); +// +// var shiftExpected = gear != newGear; //Different Gear +// shiftExpected = shiftRequired || gbx.Disengaged; //Gearbox was disengaged +// +// Assert.AreEqual(shiftExpected, shiftRequired); +// } +// +// +// [TestCase(2, true, 3, true, 100, 1800, 13, Description = "Upshift-TCLocked", TestName="Upshift-TCLocked")] +// [TestCase(1, false, 1, true, 100, 1000, 1, Description = "Upshift-TC", TestName = "Upshift-TC")] +// +// +// [TestCase(2, true, 3, true, 100, 800, 13, Description = "Upshift-TCLocked", TestName = "EarlyUpshift")] +// +// [TestCase(1, false, 1, true, 100, 500, 1, Description = "EarlyUpshift-TC", TestName="EarlyUpshift-TC")] +// public void Gearbox_Upshift(int gear, bool tcLocked, int newGear, bool newTcLocked, double tqNm, double nRPM, double speedKmh) +// { +// var gearRatios = new[] { 3.4, 1.9, 1.42, 1.0, 0.7, 0.62 }; +// +// var vehicleContainer = GetMockVehicleContainer( +// speedKmh, +// DrivingBehavior.Accelerating, +// gearRatios, +// out var inputData, out var runData, out var gearboxData, out var simplePt); +// +// +// var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); +// var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); +// +// var gbxResponse = gbx.Initialize(0.SI<NewtonMeter>(), angularVelocity); +// +// Assert.AreEqual((uint)gear, gbx.Gear.Gear); +// Assert.That(gbx.Gear.TorqueConverterLocked, Is.EqualTo(tcLocked)); +// +// +// var absTime = 0.SI<Second>(); +// var dt = 2.SI<Second>(); +// +// gbx.CurrentState = new ATGearbox.ATGearboxState() +// { +// Disengaged = gbx.Disengaged, +// Gear = gbx.Gear, +// }; +// +// +// var inAngularVelocity = nRPM.RPMtoRad(); +// var outAngularVelocity = inAngularVelocity / gearRatios[gear]; +// +// var inTorque = tqNm.SI<NewtonMeter>(); +// var outTortque = inTorque * gearRatios[gear]; +// +// var response = new ResponseSuccess(this); +// response.Engine.DynamicFullLoadTorque = 50.SI<NewtonMeter>(); +// response.Engine.EngineSpeed = inAngularVelocity; +// response.Engine.TorqueOutDemand = inTorque; +// +// +// runData.GearshiftParameters.RatingFactorCurrentGear = 1.1; +// +// +// var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, outTortque, outAngularVelocity, inTorque, inAngularVelocity, gbx.Gear, -double.MaxValue.SI<Second>(), response); +// +// +// Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(newGear)); +// Assert.That(shiftStrategy.NextGear.TorqueConverterLocked ?? true, Is.EqualTo(newTcLocked)); +// +// var shiftExpected = gear != newGear; //Different Gear +// shiftExpected = shiftRequired || gbx.Disengaged; //Gearbox was disengaged +// +// Assert.AreEqual(shiftExpected, shiftRequired); +// } +// +// +// [TestCase(2, true, 3, true, 100, 1800, 13, Description = "Upshift-TCLocked")] +// [TestCase(1, false, 1, true, 100, 1000, 1, Description = "Upshift-TC")] +// public void Gearbox_EarlyUpshift(int gear, bool tcLocked, int newGear, bool newTcLocked, double tqNm, double nRPM, double speedKmh) +// { +// var gearRatios = new[] { 3.4, 1.9, 1.42, 1.0, 0.7, 0.62 }; +// +// var vehicleContainer = GetMockVehicleContainer( +// speedKmh, +// DrivingBehavior.Accelerating, +// gearRatios, +// out var inputData, out var runData, out var gearboxData, out _); +// +// +// var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); +// var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); +// +// var response = gbx.Initialize(0.SI<NewtonMeter>(), angularVelocity); +// +// Assert.AreEqual((uint)gear, gbx.Gear.Gear); +// Assert.That(gbx.Gear.TorqueConverterLocked, Is.EqualTo(tcLocked)); +// +// +// var absTime = 0.SI<Second>(); +// var dt = 2.SI<Second>(); +// +// gbx.CurrentState = new ATGearbox.ATGearboxState() +// { +// Disengaged = gbx.Disengaged, +// Gear = gbx.Gear, +// }; +// +// +// var inAngularVelocity = nRPM.RPMtoRad(); +// var outAngularVelocity = inAngularVelocity / gearRatios[gear]; +// +// var inTorque = tqNm.SI<NewtonMeter>(); +// var outTortque = inTorque * gearRatios[gear]; +// +// var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, outTortque, outAngularVelocity, inTorque, inAngularVelocity, gbx.Gear, -double.MaxValue.SI<Second>(), new ResponseSuccess(this)); +// +// +// Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(newGear)); +// Assert.That(shiftStrategy.NextGear.TorqueConverterLocked ?? true, Is.EqualTo(newTcLocked)); +// +// var shiftExpected = gear != newGear; //Different Gear +// shiftExpected = shiftRequired || gbx.Disengaged; //Gearbox was disengaged +// +// Assert.AreEqual(shiftExpected, shiftRequired); +// } +// +// +// [TestCase(1, false, 2, false, 100, 1000, 1, Description = "Upshift-TC")] +// public void Gearbox_Upshift_TC_TC(int gear, bool tcLocked, int newGear, bool newTcLocked, double tqNm, double nRPM, double speedKmh) +// { +// var gearRatios = new[] { 3.4, 1.3, 1.1, 1.0, 0.7, 0.62 }; +// +// var vehicleContainer = GetMockVehicleContainer( +// speedKmh, +// DrivingBehavior.Accelerating, +// gearRatios, +// out var inputData, out var runData, out var gearboxData, out _); +// +// +// var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); +// var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); +// +// var gbxResponse = gbx.Initialize(0.SI<NewtonMeter>(), angularVelocity); +// +// Assert.AreEqual((uint)gear, gbx.Gear.Gear); +// Assert.That(gbx.Gear.TorqueConverterLocked, Is.EqualTo(tcLocked)); +// +// +// var absTime = 0.SI<Second>(); +// var dt = 2.SI<Second>(); +// +// gbx.CurrentState = new ATGearbox.ATGearboxState() +// { +// Disengaged = gbx.Disengaged, +// Gear = gbx.Gear, +// }; +// +// Assert.That(gbx.ModelData.GearList.First(p => p.Gear == 2).TorqueConverterLocked, Is.False, "Expected 2nd gear with TC"); +// var inAngularVelocity = nRPM.RPMtoRad(); +// var outAngularVelocity = inAngularVelocity / gearRatios[gear]; +// +// var inTorque = tqNm.SI<NewtonMeter>(); +// var outTortque = inTorque * gearRatios[gear]; +// +// var response = new ResponseSuccess(this); +// response.Engine.EngineSpeed = inAngularVelocity; +// response.Engine.TorqueOutDemand = inTorque; +// +// +// var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, outTortque, outAngularVelocity, inTorque, inAngularVelocity, gbx.Gear, -double.MaxValue.SI<Second>(), response); +// +// +// Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(newGear)); +// Assert.That(shiftStrategy.NextGear.TorqueConverterLocked ?? true, Is.EqualTo(newTcLocked)); +// +// var shiftExpected = gear != newGear; //Different Gear +// shiftExpected = shiftRequired || gbx.Disengaged; //Gearbox was disengaged +// +// Assert.AreEqual(shiftExpected, shiftRequired); +// } +// +// +// +// +// [TestCase(3, true, 2, true, 900, 600, 15, Description = "Downshift", TestName="Gearbox_DownShift_1")] +// public void Gearbox_Downshift(int gear, bool tcLocked, int newGear, bool newTcLocked, double tqNm, double nRPM, double speedKmh) +// { +// var gearRatios = new[] { 3.4, 1.9, 1.42, 1.0, 0.7, 0.62 }; +// +// var vehicleContainer = GetMockVehicleContainer( +// speedKmh, +// DrivingBehavior.Accelerating, +// gearRatios, +// out var inputData, out var runData, out var gearboxData, out var simplePt); +// +// vehicleContainer.Setup(v => v.DriverInfo.DrivingAction).Returns(DrivingAction.Accelerate); +// +// var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); +// var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); +// +// var gbxResponse = gbx.Initialize(0.SI<NewtonMeter>(), angularVelocity); +// +// Assert.AreEqual((uint)gear, gbx.Gear.Gear); +// Assert.That(gbx.Gear.TorqueConverterLocked, Is.EqualTo(tcLocked)); +// +// +// var absTime = 0.SI<Second>(); +// var dt = 2.SI<Second>(); +// +// gbx.CurrentState = new ATGearbox.ATGearboxState() +// { +// Disengaged = gbx.Disengaged, +// Gear = gbx.Gear, +// }; +// +// +// var inAngularVelocity = nRPM.RPMtoRad(); +// var outAngularVelocity = inAngularVelocity / gearRatios[gear]; +// +// var inTorque = tqNm.SI<NewtonMeter>(); +// var outTortque = inTorque * gearRatios[gear]; +// +// var response = new ResponseSuccess(this); +// response.Engine.EngineSpeed = inAngularVelocity; +// response.Engine.TorqueOutDemand = inTorque; +// +// +// var mockPort = new Mock<ITnOutPort>(); +// +// simplePt.Setup(s => s.GearboxOutPort).Returns(mockPort.Object); +// mockPort.Setup(p => p.Request( +// It.IsAny<Second>(), +// It.IsAny<Second>(), +// It.IsAny<NewtonMeter>(), +// It.IsAny<PerSecond>(), +// true +// )).Returns((Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, bool dryRun) => { +// var response = new ResponseDryRun(this); +// response.Engine.PowerRequest = outTorque * outAngularVelocity; +// return response; +// }); +// +// +// +// +// var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, outTortque, outAngularVelocity, inTorque, inAngularVelocity, gbx.Gear, -double.MaxValue.SI<Second>(), response); +// +// +// Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(newGear)); +// Assert.That(shiftStrategy.NextGear.TorqueConverterLocked ?? true, Is.EqualTo(newTcLocked)); +// +// var shiftExpected = gear != newGear; //Different Gear +// shiftExpected = shiftRequired || gbx.Disengaged; //Gearbox was disengaged +// +// Assert.AreEqual(shiftExpected, shiftRequired); +// } +// +// [TestCase(3, true, 2, true, 200, 700, 15, Description = "Downshift_3", TestName = "Gearbox_DownShift_3")] +// public void Gearbox_Downshift_2(int gear, bool tcLocked, int newGear, bool newTcLocked, double tqNm, double nRPM, +// double speedKmh) +// { +// var gearRatios = new[] { 3.4, 1.9, 1.42, 1.0, 0.7, 0.62 }; +// +// var vehicleContainer = GetMockVehicleContainer( +// speedKmh, +// DrivingBehavior.Accelerating, +// gearRatios, +// out var inputData, out var runData, out var gearboxData, out _); +// +// vehicleContainer.Setup(v => v.DriverInfo.DrivingAction).Returns(DrivingAction.Accelerate); +// +// // Condition from ATShiftStrategy +// //if (DataBus.VehicleInfo.VehicleSpeed < DataBus.DrivingCycleInfo.CycleData.LeftSample.VehicleTargetSpeed - 10.KMPHtoMeterPerSecond() && +// // DataBus.DriverInfo.DriverAcceleration < 0.SI<MeterPerSquareSecond>()) +// vehicleContainer.Setup(v => v.DrivingCycleInfo.CycleData).Returns(new CycleData() { +// LeftSample = new DrivingCycleData.DrivingCycleEntry() { +// VehicleTargetSpeed = 30.KMPHtoMeterPerSecond() +// } +// }); +// +// vehicleContainer.Setup(v => v.DriverInfo.DriverAcceleration).Returns(-0.1.SI<MeterPerSquareSecond>()); +// +// +// runData.EngineData.Inertia = 1.SI<KilogramSquareMeter>(); +// var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx, out var gbxNextComponent); +// +// +// var dryRunResponse = new ResponseDryRun(this); +// dryRunResponse.Engine.EngineSpeed = +// vehicleContainer.Object.EngineInfo.EngineN95hSpeed - 1.SI<PerSecond>(); +// dryRunResponse.DeltaFullLoad = 40_000.SI<Watt>(); +// +// +// gbxNextComponent.Setup(c => c.Request( +// It.IsAny<Second>(), +// It.IsAny<Second>(), +// It.IsAny<NewtonMeter>(), +// It.IsAny<PerSecond>(), true)).Returns( +// dryRunResponse); +// +// var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); +// +// var response = gbx.Initialize(0.SI<NewtonMeter>(), angularVelocity); +// +// Assert.AreEqual((uint)gear, gbx.Gear.Gear); +// Assert.That(gbx.Gear.TorqueConverterLocked, Is.EqualTo(tcLocked)); +// +// +// var absTime = 0.SI<Second>(); +// var dt = 2.SI<Second>(); +// +// gbx.CurrentState = new ATGearbox.ATGearboxState() +// { +// Disengaged = gbx.Disengaged, +// Gear = gbx.Gear, +// }; +// +// +// var inAngularVelocity = nRPM.RPMtoRad(); +// var outAngularVelocity = inAngularVelocity / gearRatios[gear]; +// +// var inTorque = tqNm.SI<NewtonMeter>(); +// var outTortque = inTorque * gearRatios[gear]; +// +// var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, outTortque, outAngularVelocity, inTorque, inAngularVelocity, gbx.Gear, -double.MaxValue.SI<Second>(), new ResponseSuccess(this)); +// +// +// Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(newGear)); +// Assert.That(shiftStrategy.NextGear.TorqueConverterLocked ?? true, Is.EqualTo(newTcLocked)); +// +// var shiftExpected = gear != newGear; //Different Gear +// shiftExpected = shiftRequired || gbx.Disengaged; //Gearbox was disengaged +// +// Assert.AreEqual(shiftExpected, shiftRequired); +// } +// +// [TestCase(3, true, 2, true, 1700, 700, 15, Description = "Downshift", TestName = "Gearbox_Early_DownShift_1")] +// public void Gearbox_Early_Downshift(int gear, bool tcLocked, int newGear, bool newTcLocked, double tqNm, double nRPM, double speedKmh) +// { +// var gearRatios = new[] { 3.4, 1.9, 1.42, 1.0, 0.7, 0.62 }; +// +// var vehicleContainer = GetMockVehicleContainer( +// speedKmh, +// DrivingBehavior.Accelerating, +// gearRatios, +// out var inputData, out var runData, out var gearboxData, out var simplePt); +// +// vehicleContainer.Setup(v => v.DriverInfo.DrivingAction).Returns(DrivingAction.Accelerate); +// +// var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); +// var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); +// +// var gbxResponse = gbx.Initialize(0.SI<NewtonMeter>(), angularVelocity); +// +// Assert.AreEqual((uint)gear, gbx.Gear.Gear); +// Assert.That(gbx.Gear.TorqueConverterLocked, Is.EqualTo(tcLocked)); +// +// +// var absTime = 0.SI<Second>(); +// var dt = 2.SI<Second>(); +// +// gbx.CurrentState = new ATGearbox.ATGearboxState() +// { +// Disengaged = gbx.Disengaged, +// Gear = gbx.Gear, +// }; +// +// +// var inAngularVelocity = nRPM.RPMtoRad(); +// var outAngularVelocity = inAngularVelocity / gearRatios[gear]; +// +// var inTorque = tqNm.SI<NewtonMeter>(); +// var outTortque = inTorque * gearRatios[gear]; +// +// var response = new ResponseSuccess(this); +// response.Engine.EngineSpeed = inAngularVelocity; +// response.Engine.TorqueOutDemand = inTorque; +// +// +// var mockPort = new Mock<ITnOutPort>(); +// +// simplePt.Setup(s => s.GearboxOutPort).Returns(mockPort.Object); +// mockPort.Setup(p => p.Request( +// It.IsAny<Second>(), +// It.IsAny<Second>(), +// It.IsAny<NewtonMeter>(), +// It.IsAny<PerSecond>(), +// true +// )).Returns((Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, bool dryRun) => { +// var response = new ResponseDryRun(this); +// response.Engine.PowerRequest = outTorque * outAngularVelocity; +// return response; +// }); +// +// +// +// +// var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, outTortque, outAngularVelocity, inTorque, inAngularVelocity, gbx.Gear, -double.MaxValue.SI<Second>(), response); +// +// +// Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(newGear)); +// Assert.That(shiftStrategy.NextGear.TorqueConverterLocked ?? true, Is.EqualTo(newTcLocked)); +// +// var shiftExpected = gear != newGear; //Different Gear +// shiftExpected = shiftRequired || gbx.Disengaged; //Gearbox was disengaged +// +// Assert.AreEqual(shiftExpected, shiftRequired); +// } +// +// private ATShiftStrategy GetShiftStrategyAndGearbox(Mock<IVehicleContainer> vehicleContainer, out ATGearbox gbx) +// { +// return GetShiftStrategyAndGearbox(vehicleContainer, out gbx, out _); +// } +// +// private ATShiftStrategy GetShiftStrategyAndGearbox(Mock<IVehicleContainer> vehicleContainer, out ATGearbox gbx, +// out Mock<ITnOutPort> gbxNextComponent) +// { +// var shiftStrategy = new ATShiftStrategyOptimized(vehicleContainer.Object); +// +// gbx = new ATGearbox(vehicleContainer.Object, shiftStrategy); +// var mockPort = new Mock<ITnOutPort>(); +// NewtonMeter tqRequest = null; +// PerSecond rpmRequest = null; +// mockPort.Setup(p => p.Initialize(It.IsAny<NewtonMeter>(), +// It.IsAny<PerSecond>())).Returns((NewtonMeter tq, PerSecond rpm) => { +// tqRequest = tq; +// rpmRequest = rpm; +// return new ResponseSuccess(this) +// { +// Engine = { +// EngineSpeed = rpm, +// PowerRequest = tq * rpm, +// }, +// }; +// }); +// mockPort.Setup(p => p.Request(It.IsAny<Second>(), It.IsAny<Second>(), It.IsAny<NewtonMeter>(), +// It.IsAny<PerSecond>(), true)).Returns(new ResponseDryRun(this)); +// +// var idleController = new Mock<IIdleController>(); +// +// +// gbx.IdleController = idleController.Object; +// gbx.Connect(mockPort.Object); +// +// gbxNextComponent = mockPort; +// return shiftStrategy; +// } +// +// /// <summary> +// /// Calculated the angular velocity based on the vehicle speed +// /// </summary> +// /// <param name="speedKmh"></param> +// /// <param name="runData"></param> +// /// <returns></returns> +// private static PerSecond GetAngularVelocityBySpeed(double speedKmh, VectoRunData runData) +// { +// // r_dyn = 0.465m, i_axle = 6.2 +// var angularVelocity = +// speedKmh.KMPHtoMeterPerSecond() +// / runData.VehicleData.DynamicTyreRadius * 6.2; +// return angularVelocity; +// } +// +// private Mock<IVehicleContainer> GetMockVehicleContainer(double speedKmh, DrivingBehavior driverBehavior, +// double[] gearRatios, +// out IVehicleDeclarationInputData inputData, out VectoRunData runData, out GearboxData gearboxData, +// out Mock<ISimpleVehicleContainer> simplePt) +// { +// inputData = GetMockInputData(gearRatios); +// var gbxTypes = new[] { +// GearboxType.ATSerial +// }; +// var runDataLocal = GetDummyVectoRunData(inputData); +// var shiftPolygonCalc = GetShiftPolygonCalculator(true); +// +// +// //Setup VehicleContainer +// var vehicleContainer = new Mock<IVehicleContainer>(); +// var vehicleInfo = new Mock<IVehicleInfo>(); +// +// vehicleContainer.Setup(c => c.RunData).Returns(runDataLocal); +// vehicleContainer.Setup(c => c.VehicleInfo).Returns(vehicleInfo.Object); +// +// +// //EngineInfo +// var engineInfo = new Mock<IEngineInfo>(); +// vehicleContainer.Setup(c => c.EngineInfo).Returns(engineInfo.Object); +// engineInfo.Setup(e => e.EngineIdleSpeed).Returns(runDataLocal.EngineData.IdleSpeed); +// engineInfo.Setup(e => e.EngineRatedSpeed).Returns(runDataLocal.EngineData.FullLoadCurves.First().Value.RatedSpeed); +// +// engineInfo.Setup(e => e.EngineSpeed).Returns(1400.RPMtoRad()); +// engineInfo.Setup(e => e.EngineN95hSpeed).Returns +// (runDataLocal.EngineData.FullLoadCurves.First().Value.N95hSpeed); +// engineInfo.Setup(e => e.EngineN80hSpeed).Returns( +// runDataLocal.EngineData.FullLoadCurves.First().Value.N80hSpeed); +// engineInfo.Setup(e => e.EngineStationaryFullPower(It.IsAny<PerSecond>())).Returns((PerSecond n) => +// runDataLocal.EngineData.FullLoadCurves[0].FullLoadStationaryPower(n)); +// +// //VehicleInfo +// vehicleInfo.Setup(v => v.VehicleSpeed).Returns(speedKmh.KMPHtoMeterPerSecond()); +// vehicleInfo.Setup(v => v.AirDragResistance(It.IsAny<MeterPerSecond>(), It.IsAny<MeterPerSecond>())) +// .Returns(0.SI<Newton>()); +// vehicleInfo.Setup(v => v.RollingResistance(It.IsAny<Radian>())).Returns(0.SI<Newton>()); +// vehicleInfo.Setup(v => v.SlopeResistance(It.IsAny<Radian>())).Returns(0.SI<Newton>()); +// vehicleInfo.Setup(v => v.TotalMass).Returns(12000.SI<Kilogram>()); +// +// //AxleGearInfo +// var axleGearInfo = new Mock<IAxlegearInfo>(); +// vehicleContainer.Setup(c => c.AxlegearInfo).Returns(axleGearInfo.Object); +// axleGearInfo.Setup(a => a.AxlegearLoss()).Returns(0.SI<Watt>()); +// +// //WheelsInfo +// var wi = new Mock<IWheelsInfo>(); +// vehicleContainer.Setup(c => c.WheelsInfo).Returns(wi.Object); +// wi.Setup(w => w.ReducedMassWheels).Returns(0.SI<Kilogram>()); +// +// //Cycle Info +// var cycleInfo = new Mock<IDrivingCycleInfo>(); +// vehicleContainer.Setup(c => c.DrivingCycleInfo).Returns(cycleInfo.Object); +// cycleInfo.Setup(c => c.CycleData).Returns( +// GetCycleData()); +// cycleInfo.Setup(c => c.RoadGradient).Returns(0.SI<Radian>()); +// +// +// cycleInfo.Setup(c => c.CycleLookAhead(It.IsAny<Meter>())).Returns(new DrivingCycleData.DrivingCycleEntry() +// { +// Altitude = 0.SI<Meter>() +// }); +// cycleInfo.Setup(c => c.Altitude).Returns(0.SI<Meter>()); +// +// //DriverINfo +// vehicleContainer.Setup(v => v.DriverInfo.DriverBehavior).Returns(driverBehavior); +// var acc = 0.SI<MeterPerSquareSecond>(); +// switch (driverBehavior) +// { +// case DrivingBehavior.Accelerating: +// acc = 1.SI<MeterPerSquareSecond>(); +// break; +// case DrivingBehavior.Braking: +// acc = -1.SI<MeterPerSquareSecond>(); +// break; +// case DrivingBehavior.Halted: +// acc = 0.SI<MeterPerSquareSecond>(); +// break; +// default: +// throw new ArgumentOutOfRangeException(); +// } +// +// +// +// +// vehicleContainer.Setup(v => v.DriverInfo.DriverAcceleration).Returns(acc); +// runData = runDataLocal; +// gearboxData = runData.GearboxData; +// +// +// //TestPowertrain +// //TestPowertrainBuilder +// var testPt = GetMockTestPowertrain(runData); +// +// var ptBuilder = new Mock<ISimplePowertrainBuilder>(); +// ptBuilder.Setup(p => p.CreateTestPowertrain<Gearbox>(It.IsAny<ISimpleVehicleContainer>(), It.IsAny<IDataBus>())) +// .Returns(testPt.Object); +// simplePt = GetSimplePowertrain(inputData); +// ptBuilder.Setup(ptBuilder => ptBuilder.BuildSimplePowertrain(It.IsAny<VectoRunData>())) +// .Returns(simplePt.Object); +// +// +// vehicleContainer.Setup(c => c.SimplePowertrainBuilder).Returns(ptBuilder.Object); +// +// return vehicleContainer; +// } +// +// private Mock<IPowertainInfo> GetPowertrainInfo() +// { +// var powerTrainInfo = new Mock<IPowertainInfo>(); +// powerTrainInfo.Setup(p => p.HasCombustionEngine).Returns(true); +// return powerTrainInfo; +// } +// +// private Mock<ITestPowertrain<Gearbox>> GetMockTestPowertrain(VectoRunData runData) +// { +// var testPt = new Mock<ITestPowertrain<Gearbox>>(); +// var tCnt = new Mock<ISimpleVehicleContainer>(); +// tCnt.Setup(c => c.RunData).Returns(runData); +// +// tCnt.Setup(c => c.PowertrainInfo).Returns(GetPowertrainInfo().Object); +// +// +// var tGbx = new Mock<Gearbox>(tCnt.Object, null); +// testPt.Setup(t => t.Gearbox).Returns(tGbx.Object); +// tGbx.Setup(g => g.Initialize(It.IsAny<NewtonMeter>(), It.IsAny<PerSecond>())) +// .Returns((NewtonMeter t, PerSecond n) => new ResponseSuccess(this) +// { +// Engine = { PowerRequest = n * t, EngineSpeed = n }, +// Clutch = { PowerRequest = n * t } +// }); +// tGbx.Setup(g => g.Request(It.IsAny<Second>(), It.IsAny<Second>(), It.IsAny<NewtonMeter>(), It.IsAny<PerSecond>(), +// It.IsAny<bool>())) +// .Returns((Second absTime, Second dt, NewtonMeter t, PerSecond n, bool dryRun) => new ResponseSuccess(this) +// { +// Engine = { PowerRequest = n * t, EngineSpeed = n }, +// Clutch = { PowerRequest = n * t } +// }); +// tGbx.Setup(g => g.Request(It.IsAny<Second>(), It.IsAny<Second>(), It.IsAny<NewtonMeter>(), It.IsAny<PerSecond>(), +// It.IsAny<bool>())) +// .Returns((Second absTime, Second dt, NewtonMeter t, PerSecond n, bool dryRun) => dryRun ? +// new ResponseDryRun(this) +// { +// Engine = { PowerRequest = n * t, EngineSpeed = n }, +// Clutch = { PowerRequest = n * t } +// } : new ResponseSuccess(this) +// { +// Engine = { PowerRequest = n * t, EngineSpeed = n }, +// Clutch = { PowerRequest = n * t } +// }); +// var tEng = new Mock<ICombustionEngine>(); +// testPt.Setup(t => t.CombustionEngine).Returns(tEng.Object); +// tEng.Setup(e => e.EngineStationaryFullPower(It.IsAny<PerSecond>())) +// .Returns((PerSecond n) => runData.EngineData.FullLoadCurves[0].FullLoadStationaryPower(n)); +// return testPt; +// } +// +// private CycleData GetCycleData() +// { +// return new CycleData() +// { +// LeftSample = new DrivingCycleData.DrivingCycleEntry() +// { +// PTOActive = PTOActivity.Inactive, +// VehicleTargetSpeed = 10.KMPHtoMeterPerSecond() +// } +// }; +// } +// +// +// +// [TestCase(2, 3, 400, 2300, 5, DrivingBehavior.Accelerating, Description = "Upshift")] +// public void Gearbox_EmergencyShift(int gear, int newGear, double tqNm, double nRPM, double speedKmh, +// DrivingBehavior driverBehavior) +// { +// +// } +// +// +// private static VectoRunData GetDummyVectoRunData(IVehicleDeclarationInputData inputData) +// { +// var nrOfGears = inputData.Components.GearboxInputData.Gears.Count; +// var fldData = InputDataHelper.InputDataAsTableData(EngineFldHeader, EngineFldData); +// var fld = FullLoadCurveReader.Create(fldData); +// +// +// // create gearbox data +// var tcDataAdapter = new TorqueConverterDataAdapter(); +// +// +// +// // fuel data +// var fuelData = new CombustionEngineFuelData() { +// ConsumptionMap = FuelConsumptionMapReader.Create( +// InputDataHelper.InputDataAsTableData( +// "engine speed [rpm] ,torque [Nm] ,fuel consumption [g/h] ,whr power electrical [W]", +// "500,-131,0,0", +// "500,95.6,1814.959,0", +// "500,573.6,9771.095,0", +// "2453,-209.12,0,0", +// "2453,764.8,39097.94,0" +// )), +// FuelData = DeclarationData.FuelData.Lookup(FuelType.DieselCI), +// +// +// }; +// +// var runData = new VectoRunData() { +// VehicleData = new VehicleData() { +// DynamicTyreRadius = 0.465.SI<Meter>(), +// GrossVehicleMass = 12_000.SI<Kilogram>(), +// CurbMass = 10_000.SI<Kilogram>(), +// }, +// EngineData = new CombustionEngineData() { +// Inertia = 0.SI<KilogramSquareMeter>(), +// FullLoadCurves = new Dictionary<uint, EngineFullLoadCurve>(), +// IdleSpeed = 600.RPMtoRad(), +// RatedSpeedDeclared = 2000.RPMtoRad(), +// Fuels = new List<CombustionEngineFuelData>() { +// fuelData, +// } +// }, +// Cycle = new DrivingCycleData() { +// CycleType = CycleType.DistanceBased +// } +// }; +// for (uint i = 0; i <= nrOfGears; i++) { +// runData.EngineData.FullLoadCurves[i] = fld; +// } +// +// var gbxDataAdapter = new GearboxDataAdapter(tcDataAdapter); +// var gbxTypes = new[] { +// GearboxType.ATSerial, GearboxType.ATPowerSplit +// }; +// +// var gearboxData = gbxDataAdapter.CreateGearboxData(inputData, runData, new ATShiftStrategyOptimizedPolygonCalculator(), new GearboxType[] { +// GearboxType.ATSerial, +// GearboxType.ATPowerSplit +// }); +// +// var gearShiftParams = +// gbxDataAdapter.CreateGearshiftData(1.0, runData.EngineData.IdleSpeed, GearboxType.ATSerial, nrOfGears); +// +// runData.GearboxData = gearboxData; +// runData.GearshiftParameters = gearShiftParams; +// return runData; +// } +// +// private static IShiftPolygonCalculator GetShiftPolygonCalculator(bool optimized) +// { +// +// IShiftPolygonCalculator shiftPolygonCalc = optimized ? new ATShiftStrategyOptimizedPolygonCalculator() : new ATShiftStrategyPolygonCalculator(); +// +// return shiftPolygonCalc; +// } +// +// // private static IShiftPolygonCalculator GetMockShiftPolygonCalc() +// // { +// // var shiftPolygonCalc = new Mock<IShiftPolygonCalculator>(); +// // var downshift = new List<ShiftPolygon.ShiftPolygonEntry>() { }; +// // var upshift = new List<ShiftPolygon.ShiftPolygonEntry>() { }; +// // var shiftpolygon = new ShiftPolygon(downshift, upshift); +// // shiftPolygonCalc.Setup(s => s.ComputeDeclarationShiftPolygon(It.IsIn(GearboxType.ATSerial), It.IsAny<int>(), +// // It.IsAny<EngineFullLoadCurve>(), It.IsAny<IList<ITransmissionInputData>>(), +// // It.IsAny<CombustionEngineData>(), It.IsAny<double>(), It.IsAny<Meter>(), It.IsAny<ElectricMotorData>())) +// // .Returns(shiftpolygon); +// // return shiftPolygonCalc.Object; +// // } +// +// private Mock<ISimpleVehicleContainer> GetSimplePowertrain(IVehicleDeclarationInputData inputData) +// { +// var simplePt = new Mock<ISimpleVehicleContainer>(); +// simplePt.Setup(s => s.RunData).Returns(GetDummyVectoRunData(inputData)); +// simplePt.Setup(s => s.AddComponent(It.IsAny<VectoSimulationComponent>())); +// simplePt.Setup(s => s.PowertrainInfo).Returns(GetPowertrainInfo().Object); +// simplePt.Setup(s => s.GearboxCtl).Returns(GetMockGearbox(simplePt.Object).Object); +// +// //Vehicle Info +// var vehicleInfo = new Mock<IVehicleInfo>(); +// simplePt.Setup(c => c.VehicleInfo).Returns(vehicleInfo.Object); +// vehicleInfo.Setup(v => v.VehicleSpeed).Returns(1.KMPHtoMeterPerSecond()); +// +// +// //VehiclePort +// var vehiclePort = new Mock<IDriverDemandOutPort>(); +// vehiclePort.Setup(port => port.Initialize( +// It.IsAny<MeterPerSecond>(), It.IsAny<Radian>())).Returns(new ResponseSuccess(this)); +// +// simplePt.Setup(c => c.VehiclePort).Returns(vehiclePort.Object); +// +// var mockPort = new Mock<ITnOutPort>(); +// +// mockPort.Setup(p => p.Initialize(It.IsAny<NewtonMeter>(), +// It.IsAny<PerSecond>())).Returns((NewtonMeter tq, PerSecond rpm) => { +// return new ResponseSuccess(this) +// { +// Engine = { +// EngineSpeed = rpm, +// PowerRequest = tq * rpm, +// }, +// }; +// }); +// mockPort.Setup(p => p.Request( +// It.IsAny<Second>(), +// It.IsAny<Second>(), +// It.IsAny<NewtonMeter>(), +// It.IsAny<PerSecond>(), +// true)).Returns(( +// Second absTime, +// Second dt, +// NewtonMeter tq, +// PerSecond ang, +// bool dryRun) => { +// return new ResponseDryRun(this) { +// Engine = { +// EngineSpeed = ang, +// PowerRequest = tq * ang, +// TorqueOutDemand = tq +// }, +// DeltaFullLoad = 10_000.SI<Watt>(), +// }; +// }); +// +// simplePt.Setup(c => c.GearboxOutPort).Returns(mockPort.Object); +// return simplePt; +// } +// private Mock<ATGearbox> GetMockGearbox(IVehicleContainer container) +// { +// var gbx = new Mock<ATGearbox>(container, null); +// var ratios = container.RunData.GearboxData.Gears; +// +// +// gbx.Setup(g => g.LastUpshift).Returns(-double.MaxValue.SI<Second>()); +// gbx.Setup(g => g.LastDownshift).Returns(-double.MaxValue.SI<Second>()); +// gbx.SetupProperty(g => g.Gear); +// gbx.Setup(g => g.Request(It.IsAny<Second>(), It.IsAny<Second>(), It.IsAny<NewtonMeter>(), It.IsAny<PerSecond>(), +// It.IsAny<bool>())) +// .Returns((Second absTime, Second dt, NewtonMeter t, PerSecond n, bool dryRun) => { +// var ratio = gbx.Object.Gear == null ? 1.0 : ratios[gbx.Object.Gear.Gear].Ratio; +// return dryRun +// ? new ResponseDryRun(this) +// { +// Engine = { +// PowerRequest = n * t, EngineSpeed = n * ratio, +// DynamicFullLoadPower = (t / ratio + 2300.SI<NewtonMeter>()) * n * ratio, +// }, +// Clutch = { PowerRequest = n * t }, +// DeltaFullLoad = 10.SI<Watt>() +// } +// : new ResponseSuccess(this) +// { +// Engine = { PowerRequest = n * t, EngineSpeed = n * ratio }, +// Clutch = { PowerRequest = n * t } +// }; +// }); +// return gbx; +// } +// +// +// private IVehicleDeclarationInputData GetMockInputData(double[]? gearRatios) +// { +// var input = new Mock<IVehicleDeclarationInputData>(); +// var components = new Mock<IVehicleComponentsDeclaration>(); +// input.Setup(i => i.Components).Returns(components.Object); +// var gbx = new Mock<IGearboxDeclarationInputData>(); +// var tc = new Mock<ITorqueConverterDeclarationInputData>(); +// +// components.Setup(c => c.GearboxInputData).Returns(gbx.Object); +// components.Setup(c => c.TorqueConverterInputData).Returns(tc.Object); +// gearRatios = gearRatios ?? new double[] { +// +// }; +// var header = "Input Speed [rpm],Input Torque [Nm],Torque Loss [Nm]"; +// var efficiency = 0.98; +// var data = new List<string>(); +// +// foreach (var speed in new[] {0, 10000}) { +// foreach (var tq in new[] {1e5, -1e5, 0}) { +// data.Add(FormattableString.Invariant($"{speed:f2}, {tq:f2}, {(1 - efficiency) * Math.Abs(tq)}")); +// } +// } +// var lossmap = InputDataHelper.InputDataAsTableData(header, data.ToArray()); +// //lossmap.Columns +// var gears = gearRatios.Select((x, idx) => { +// var gear = new Mock<ITransmissionInputData>(); +// gear.Setup(g => g.Ratio).Returns(x); +// gear.Setup(g => g.Gear).Returns(idx + 1); +// //gear.Setup(g => g.Efficiency).Returns(0.98); +// gear.Setup(g => g.LossMap).Returns(lossmap); +// gear.Setup(g => g.MaxInputSpeed).Returns(2000.RPMtoRad()); +// return gear.Object; +// }).ToList(); +// gbx.Setup(g => g.Type).Returns(GearboxType.ATSerial); +// gbx.Setup(g => g.Gears).Returns(gears); +// +// var tcData = InputDataHelper.InputDataAsTableData(TcHeader, TcData); +// tc.Setup(t => t.TCData).Returns(tcData); +// return input.Object; +// } +// +// public const string TcHeader = "Speed Ratio, Torque Ratio,MP1000"; +// +// public static readonly string[] TcData = new[] { +// "0.0,1.80,377.80", +// "0.1,1.71,365.21", +// "0.2,1.61,352.62", +// "0.3,1.52,340.02", +// "0.4,1.42,327.43", +// "0.5,1.33,314.84", +// "0.6,1.23,302.24", +// "0.7,1.14,264.46", +// "0.8,1.04,226.68", +// "0.9,1.02,188.90", +// "1.0,1.0,0.00", +// "1.100,0.999,-40.34", +// "1.222,0.998,-80.34", +// "1.375,0.997,-136.11", +// "1.571,0.996,-216.52", +// "1.833,0.995,-335.19", +// "2.200,0.994,-528.77", +// "2.750,0.993,-883.40", +// "4.400,0.992,-2462.17", +// "11.000,0.991,-16540.98", +// }; +// +// public const string EngineFldHeader = "engine speed [1/min],full load torque [Nm],motoring torque [Nm],PT1 [s]"; +// +// public static readonly string[] EngineFldData = new[] { +// "560,1180,-149,0.6", +// "600,1282,-148,0.6", +// "799.9999999,1791,-149,0.6", +// "1000,2300,-160,0.6", +// "1200,2300,-179,0.6", +// "1400,2300,-203,0.6", +// "1599.999999,2079,-235,0.49", +// "1800,1857,-264,0.25", +// "2000.000001,1352,-301,0.25", +// "2100,1100,-320,0.25", +// }; +// +// +// } \ No newline at end of file -- GitLab From 79dd57c8b5b946e448c9815c0c7c10896b092198 Mon Sep 17 00:00:00 2001 From: Harald Martini <harald.martini@student.tugraz.at> Date: Mon, 17 Mar 2025 12:37:10 +0100 Subject: [PATCH 13/22] added PEVAMTShiftStrategyTests.cs --- .../PEVAMTShiftStrategyTests.cs | 2023 +++++++++++++++++ 1 file changed, 2023 insertions(+) create mode 100644 Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/PEVAMTShiftStrategyTests.cs diff --git a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/PEVAMTShiftStrategyTests.cs b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/PEVAMTShiftStrategyTests.cs new file mode 100644 index 0000000000..aad578ce85 --- /dev/null +++ b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/PEVAMTShiftStrategyTests.cs @@ -0,0 +1,2023 @@ +using Moq; +using NUnit.Framework; +using TUGraz.VectoCommon.InputData; +using TUGraz.VectoCommon.Models; +using TUGraz.VectoCommon.Utils; +using TUGraz.VectoCore.InputData.Impl; +using TUGraz.VectoCore.InputData.Reader.ComponentData; +using TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.SimulationComponents; +using TUGraz.VectoCore.Models.Connector.Ports.Impl; +using TUGraz.VectoCore.Models.Declaration; +using TUGraz.VectoCore.Models.Simulation; +using TUGraz.VectoCore.Models.Simulation.Data; +using TUGraz.VectoCore.Models.Simulation.DataBus; +using TUGraz.VectoCore.Models.Simulation.Impl; +using TUGraz.VectoCore.Models.SimulationComponent; +using TUGraz.VectoCore.Models.SimulationComponent.Data; +using TUGraz.VectoCore.Models.SimulationComponent.Data.ElectricMotor; +using TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox; +using TUGraz.VectoCore.Models.SimulationComponent.Impl; +using TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies; +using TUGraz.VectoCore.Models.SimulationComponent.Strategies; +using TUGraz.VectoCore.Tests.Utils; +using TUGraz.VectoCore.Utils; +using Range = System.Range; + +// ReSharper disable InconsistentNaming + +namespace TUGraz.Vecto.UnitTests.TestCases.Components.GearShiftStrategy +{ + [TestFixture] + public class PEVAMTShiftStrategyTests + { + [TestCase(500, 80, 1)] + [TestCase(5, 500, 2)] + public void InitGear(double torque_Nm, double speed_rpm, int expectedGear) + { + // the first element 0.0 is just a placeholder for axlegear, not used in this test + var ratios = new[] { 0.0, 3.86, 1.93 }; + + var container = GetMocks(ratios); + + var shiftStrategy = GetShiftStrategyAndGearbox(container, out var gearbox); + + var absTime = 0.SI<Second>(); + var dt = 0.5.SI<Second>(); + + var torque = torque_Nm.SI<NewtonMeter>(); + var speed = speed_rpm.RPMtoRad(); + + var result = shiftStrategy.InitGear(absTime, dt, torque, speed); + + var newGear = result.Gear; + Assert.AreEqual(expectedGear, newGear); + + + + } + + [TestCase(5000, 80, 1)] + [TestCase(5, 500, 2)] + public void InitStartGear(double torque_Nm, double speed_rpm, int expectedGear) + { + // the first element 0.0 is just a placeholder for axlegear, not used in this test + var ratios = new[] { 0.0, 3.86, 1.93 }; + + var container = GetMocks(ratios); + container.Setup(c => c.VehicleInfo.VehicleSpeed).Returns(0.KMPHtoMeterPerSecond()); + + var shiftStrategy = GetShiftStrategyAndGearbox(container, out var gearbox); + + var absTime = 0.SI<Second>(); + var dt = 0.5.SI<Second>(); + + var torque = torque_Nm.SI<NewtonMeter>(); + var speed = speed_rpm.RPMtoRad(); + + var result = shiftStrategy.InitGear(absTime, dt, torque, speed); + + var newGear = result.Gear; + Assert.AreEqual(expectedGear, newGear); + + + + } + + [TestCase( + 500, + 80, + 500, + 10000, + 1, + 2, TestName = "Emergency UpShift")] + + [TestCase( + 500, + 80, + 1000, + 1800, + 1, + 2, TestName = "UpShift")] + [TestCase( + 500, + 80, + 1000, + 800, + 1, + 1, TestName = "No Upshift")] + public void Upshift(double init_outTorque_Nm, double init_outSpeed_rpm, double outTorque_Nm, + double outSpeed_rpm, int currentGear, int expectedGear) + { + CheckUpshift(init_outTorque_Nm, init_outSpeed_rpm, outTorque_Nm, outSpeed_rpm, currentGear, expectedGear, false); + } + + [TestCase( + 500, + 80, + 100, + 1800, + 1, + 3, TestName = "UpShiftSkipGear")] + public void UpshiftSkipGear(double init_outTorque_Nm, double init_outSpeed_rpm, double outTorque_Nm, + double outSpeed_rpm, int currentGear, int expectedGear) + { + CheckUpshift(init_outTorque_Nm, init_outSpeed_rpm, outTorque_Nm, outSpeed_rpm, currentGear, expectedGear, false, new[] { 0.0, 3.86, 1.93, 1.92 }); + } + + + public void CheckUpshift(double init_outTorque_Nm, double init_outSpeed_rpm, double outTorque_Nm, + double outSpeed_rpm, int currentGear, int expectedGear, bool effShift, double[]? ratios = null) + { + // the first element 0.0 is just a placeholder for axlegear, not used in this test + ratios = ratios ?? new[] { 0.0, 3.86, 1.93 }; + var ratio = ratios[currentGear]; + var container = GetMocks(ratios); + + if (!effShift) { + DisableEffshift(container.Object.RunData); + } + + + var shiftRequired = currentGear != expectedGear; + + var shiftStrategy = GetShiftStrategyAndGearbox(container, out var gearbox); + var gear = new GearshiftPosition((uint)currentGear); + gearbox.Gear = gear; + + var absTime = 0.SI<Second>(); + var dt = 0.5.SI<Second>(); + + var init_outTorque = init_outTorque_Nm.SI<NewtonMeter>(); + var init_outAngularVelocity = init_outSpeed_rpm.RPMtoRad(); + + + var outTorque = outTorque_Nm.SI<NewtonMeter>(); + var outAngularVelocity = outSpeed_rpm.RPMtoRad(); + + var inTorque = outTorque / ratio; + var inAngularVelocity = outAngularVelocity * ratio; + + var lastShiftTime = float.MinValue.SI<Second>(); + + var response = new ResponseSuccess(this); + + Console.WriteLine( + $"OutTorque: {outTorque}\n" + + $"InTorque: {inTorque} \n" + + $"OutSpeed: {outAngularVelocity.AsRPM} [rpm]\n" + + $"InSpeed: {inAngularVelocity.AsRPM} [rpm]\n"); + + + //Init gear + var initResult = shiftStrategy.InitGear(absTime, dt, init_outTorque, init_outAngularVelocity); + Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(currentGear)); + + //Check shift required + var result = shiftStrategy.ShiftRequired(absTime, dt, + outTorque: outTorque, + outAngularVelocity: outAngularVelocity, + inTorque: inTorque, + inAngularVelocity: inAngularVelocity, + gear: shiftStrategy.NextGear, + lastShiftTime: lastShiftTime, + response: response); + + Assert.AreEqual(shiftRequired, result); + Assert.AreEqual(expectedGear, shiftStrategy.NextGear.Gear); + + + + } + + [TestCase( + 500, + 80, + -10, + 1000, + 1, + 2, TestName = "UpShift")] + public void EarlyUpshift(double init_outTorque_Nm, double init_outSpeed_rpm, double outTorque_Nm, + double outSpeed_rpm, int currentGear, int expectedGear) + { + // the first element 0.0 is just a placeholder for axlegear, not used in this test + var ratios = new[] { 0.0, 3.86, 1.93 }; + var ratio = ratios[currentGear]; + var container = GetMocks(ratios); + container.Setup(c => c.VehicleInfo.VehicleSpeed).Returns(20.KMPHtoMeterPerSecond()); + + + var shiftRequired = currentGear != expectedGear; + + var shiftStrategy = GetShiftStrategyAndGearbox(container, out var gearbox); + var gear = new GearshiftPosition((uint)currentGear); + gearbox.Gear = gear; + + var absTime = 0.SI<Second>(); + var dt = 0.5.SI<Second>(); + + var init_outTorque = init_outTorque_Nm.SI<NewtonMeter>(); + var init_outAngularVelocity = init_outSpeed_rpm.RPMtoRad(); + + + var outTorque = outTorque_Nm.SI<NewtonMeter>(); + var outAngularVelocity = outSpeed_rpm.RPMtoRad(); + + var inTorque = outTorque / ratio; + var inAngularVelocity = outAngularVelocity * ratio; + + var lastShiftTime = float.MinValue.SI<Second>(); + + var response = new ResponseSuccess(this); + + Console.WriteLine( + $"OutTorque: {outTorque}\n" + + $"InTorque: {inTorque} \n" + + $"OutSpeed: {outAngularVelocity.AsRPM} [rpm]\n" + + $"InSpeed: {inAngularVelocity.AsRPM} [rpm]\n"); + + + //Init gear + var initResult = shiftStrategy.InitGear(absTime, dt, init_outTorque, init_outAngularVelocity); + Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(currentGear)); + + //Check shift required + var result = shiftStrategy.ShiftRequired(absTime, dt, + outTorque: outTorque, + outAngularVelocity: outAngularVelocity, + inTorque: inTorque, + inAngularVelocity: inAngularVelocity, + gear: shiftStrategy.NextGear, + lastShiftTime: lastShiftTime, + response: response); + + Assert.AreEqual(shiftRequired, result); + Assert.AreEqual(expectedGear, shiftStrategy.NextGear.Gear); + + + } + + + [TestCase( + 5, + 200, + 2000, + 200, + 2, + 1, TestName = "Downshift")] + public void Downshift(double init_outTorque_Nm, double init_outSpeed_rpm, double outTorque_Nm, + double outSpeed_rpm, int currentGear, int expectedGear, int speedKmh=1) + { + var ratios = new[] { 0.0, 3.86, 1.93 }; + CheckDownshift(init_outTorque_Nm, init_outSpeed_rpm, outTorque_Nm, outSpeed_rpm, currentGear, expectedGear, ratios, false, speedKmh); + } + + [TestCase( + 5, + 200, + -500, + 200, + 4, + 2, + 40, TestName = "EarlyDownshift")] + public void EarlyDownshift(double init_outTorque_Nm, double init_outSpeed_rpm, double outTorque_Nm, + double outSpeed_rpm, int currentGear, int expectedGear, int speedKmh=1) + { + var ratios = new[] { 0.0, 3.86, 3, 2.5, 1.93 }; + CheckDownshift(init_outTorque_Nm, init_outSpeed_rpm, outTorque_Nm, outSpeed_rpm, currentGear, expectedGear, ratios, true, speedKmh); + } + + [TestCase( + 5, + 200, + 2000, + 40, + 4, + 2, TestName = "Downshift_SkipGear")] + public void DownshiftSkipGears(double init_outTorque_Nm, double init_outSpeed_rpm, double outTorque_Nm, + double outSpeed_rpm, int currentGear, int expectedGear) + { + var ratios = new[] { 0.0, 3.86, 3, 2.5, 1.93 }; + CheckDownshift(init_outTorque_Nm, init_outSpeed_rpm, outTorque_Nm, outSpeed_rpm, currentGear, expectedGear, ratios, false); + } + + private void DisableEffshift(VectoRunData runData) + { + TestContext.WriteLine("EffShift Disabled"); + runData.GearshiftParameters.AllowedGearRangeFC = 0; + } + + private void DisableEffshift(Mock<IVehicleContainer> vehicleContainer) + { + DisableEffshift(vehicleContainer.Object.RunData); + } + + + [TestCase( + 5, + 200, + 2000, + 200, + 2, + 1, TestName = "BrakingGear")] + public void BrakingGear( + double init_outTorque_Nm, + double init_outSpeed_rpm, + double outTorque_Nm, + double outSpeed_rpm, + int currentGear, + int expectedGear, + int vehicleSpeed_kmH = 1) + { + // the first element 0.0 is just a placeholder for axlegear, not used in this test + var ratios = new[] { 0.0, 3.86, 1.93 }; + var ratio = ratios[currentGear]; + var container = GetMocks(ratios); + + + container.Setup(c => c.VehicleInfo.VehicleSpeed).Returns(vehicleSpeed_kmH.KMPHtoMeterPerSecond()); + container.Setup(c => c.DriverInfo.DriverBehavior).Returns(DrivingBehavior.Braking); + + + DisableEffshift(container.Object.RunData); + + + var shiftRequired = currentGear != expectedGear; + + var shiftStrategy = GetShiftStrategyAndGearbox(container, out var gearbox); + var gear = new GearshiftPosition((uint)currentGear); + gearbox.Gear = gear; + + var absTime = 0.SI<Second>(); + var dt = 0.5.SI<Second>(); + + var init_outTorque = init_outTorque_Nm.SI<NewtonMeter>(); + var init_outAngularVelocity = init_outSpeed_rpm.RPMtoRad(); + + var outTorque = outTorque_Nm.SI<NewtonMeter>(); + var outAngularVelocity = outSpeed_rpm.RPMtoRad(); + + var inTorque = outTorque / ratio; + var inAngularVelocity = outAngularVelocity * ratio; + + var lastShiftTime = float.MinValue.SI<Second>(); + + + + Console.WriteLine( + $"OutTorque: {outTorque}\n" + + $"InTorque: {inTorque} \n" + + $"OutSpeed: {outAngularVelocity}\n" + + $"InSpeed: {inAngularVelocity}\n"); + + + //Init gear + var initResult = shiftStrategy.InitGear(absTime, dt, init_outTorque, init_outAngularVelocity); + Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(currentGear)); + + var response = new ResponseSuccess(this) { }; + response.ElectricMotor.AngularVelocity = inAngularVelocity; + response.ElectricMotor.TorqueRequestEmMap = inTorque; + response.ElectricMotor.DeRatingActive = false; + response.Gearbox.InputSpeed = inAngularVelocity; + // response.ElectricMotor; + + //Check shift required + var result = shiftStrategy.ShiftRequired(absTime, dt, + outTorque: outTorque, + outAngularVelocity: outAngularVelocity, + inTorque: inTorque, + inAngularVelocity: inAngularVelocity, + gear: shiftStrategy.NextGear, + lastShiftTime: lastShiftTime, + response: response); + + Assert.AreEqual(shiftRequired, result, "Expected Shift"); + Assert.AreEqual(expectedGear, shiftStrategy.NextGear.Gear); + + + + } + + + public void CheckDownshift( + double init_outTorque_Nm, + double init_outSpeed_rpm, + double outTorque_Nm, + double outSpeed_rpm, + int currentGear, + int expectedGear, + double[] ratios, + bool effShift = true, + int vehicleSpeed_kmH = 1) + { + // the first element 0.0 is just a placeholder for axlegear, not used in this test + var ratio = ratios[currentGear]; + var container = GetMocks(ratios); + container.Setup(c => c.VehicleInfo.VehicleSpeed).Returns(vehicleSpeed_kmH.KMPHtoMeterPerSecond()); + + + if (!effShift) { + DisableEffshift(container.Object.RunData); + } + + var shiftRequired = currentGear != expectedGear; + + var shiftStrategy = GetShiftStrategyAndGearbox(container, out var gearbox); + var gear = new GearshiftPosition((uint)currentGear); + gearbox.Gear = gear; + + var absTime = 0.SI<Second>(); + var dt = 0.5.SI<Second>(); + + var init_outTorque = init_outTorque_Nm.SI<NewtonMeter>(); + var init_outAngularVelocity = init_outSpeed_rpm.RPMtoRad(); + + var outTorque = outTorque_Nm.SI<NewtonMeter>(); + var outAngularVelocity = outSpeed_rpm.RPMtoRad(); + + var inTorque = outTorque / ratio; + var inAngularVelocity = outAngularVelocity * ratio; + + var lastShiftTime = float.MinValue.SI<Second>(); + + + + Console.WriteLine( + $"OutTorque: {outTorque}\n" + + $"InTorque: {inTorque} \n" + + $"OutSpeed: {outAngularVelocity}\n" + + $"InSpeed: {inAngularVelocity}\n"); + + + //Init gear + var initResult = shiftStrategy.InitGear(absTime, dt, init_outTorque, init_outAngularVelocity); + Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(currentGear)); + + var response = new ResponseSuccess(this) { }; + response.ElectricMotor.AngularVelocity = inAngularVelocity; + response.ElectricMotor.TorqueRequestEmMap = inTorque; + response.ElectricMotor.DeRatingActive = false; + // response.ElectricMotor; + + //Check shift required + var result = shiftStrategy.ShiftRequired(absTime, dt, + outTorque: outTorque, + outAngularVelocity: outAngularVelocity, + inTorque: inTorque, + inAngularVelocity: inAngularVelocity, + gear: shiftStrategy.NextGear, + lastShiftTime: lastShiftTime, + response: response); + + Assert.AreEqual(shiftRequired, result, "Expected Shift"); + Assert.AreEqual(expectedGear, shiftStrategy.NextGear.Gear); + + + + } + + + + + + private PEVAMTShiftStrategy GetShiftStrategyAndGearbox(Mock<IVehicleContainer> container, out PEVGearbox gearbox) + { + var shiftStrategy = new PEVAMTShiftStrategy(container.Object); + gearbox = new PEVGearbox(container.Object, shiftStrategy); + + SetVelocityDropLookupData(shiftStrategy); + + gearbox.Gear = new GearshiftPosition(0); + container.Setup(c => c.GearboxInfo).Returns(gearbox); + + + return shiftStrategy; + } + + private Mock<IVehicleContainer> GetMocks(double[] ratios) + { + var container = new Mock<IVehicleContainer>(); + + //RunData + var runData = GetRunData(ratios); + container.Setup(r => r.RunData).Returns(runData); + + //EmInfo + var em = GetMockElectricMotor(container.Object, runData.ElectricMachinesData.Single().Item2); + container.Setup(c => c.ElectricMotorInfo(PowertrainPosition.BatteryElectricE2)) + .Returns(em); + container.Setup(c => c.PowertrainInfo.ElectricMotorPositions).Returns(new[] { + PowertrainPosition.BatteryElectricE2 + }); + + // container.Setup(r => r.GetElectricMotors()).Returns(new List<IElectricMotorInfo>(){em}); + + container.Setup(c => c.PowertrainInfo.HasCombustionEngine).Returns(false); + + //BatteryInfo + container.Setup(c => c.BatteryInfo.InternalVoltage).Returns(700.SI<Volt>()); + + //VehicleInfo + container.Setup(c => c.VehicleInfo.VehicleSpeed).Returns(1.KMPHtoMeterPerSecond()); + container.Setup(c => c.VehicleInfo.VehicleStopped).Returns(false); + + //DriverInfo + container.Setup(c => c.DriverInfo.DriverBehavior).Returns(DrivingBehavior.Accelerating); + container.Setup(c => c.DriverInfo.DrivingAction).Returns(DrivingAction.Accelerate); + // container.Set + + //PowertrainBuilder, SimplePowertrain + var testPt = GetTestPowertrain(ratios, container, out _); + var ptBuilder = new Mock<ISimplePowertrainBuilder>(); + container.Setup(c => c.SimplePowertrainBuilder).Returns(ptBuilder.Object); + + //DrivingCycleInfo + container.Setup(c => c.DrivingCycleInfo.RoadGradient).Returns(0.SI<Radian>()); + + return container; + } + + private Mock<ITestPowertrain> GetTestPowertrain(double[] ratios, + Mock<IVehicleContainer> container, + out Mock<ISimpleVehicleContainer> simplePt) + { + var testPt = new Mock<ITestPowertrain>(); + + simplePt = GetSimplePowertrain(ratios, container); + + return testPt; + } + + private Mock<IElectricSystem> GetMockElectricSystem() + { + var electricSystem = new Mock<IElectricSystem>(); + + + electricSystem + .Setup(es => es.Request(It.IsAny<Second>(), It.IsAny<Second>(), It.IsAny<Watt>(), true)) + .Returns((Second t, Second dt, Watt powerDemand, bool dryrun) => { + + var response = new Mock<IElectricSystemResponse>(); + response + .Setup(mr => mr.MaxPowerDrive) + .Returns(-100E3.SI<Watt>()); + response + .Setup(mr => mr.MaxPowerDrag) + .Returns(100E3.SI<Watt>()); + response + .Setup(mr => mr.RESSPowerDemand).Returns(powerDemand); + + + + + return response.Object; + }); + + + return electricSystem; + } + + private ElectricMotor GetMockElectricMotor(IVehicleContainer container, ElectricMotorData emData) + { + var emControl = new SimpleElectricMotorControl(); + + var electricMotor = new ElectricMotor(container: container, emData, emControl, + PowertrainPosition.BatteryElectricE2); + + //Connect Electric System + var es = GetMockElectricSystem(); + electricMotor.Connect(es.Object); + return electricMotor; + } + + private Mock<ISimpleVehicleContainer> GetSimplePowertrain(double[] ratios, Mock<IVehicleContainer> container) + { + var simplePt = new Mock<ISimpleVehicleContainer>(); + + var components = new List<VectoSimulationComponent>(); + + var runData = container.Object.RunData; + var em = GetMockElectricMotor(container.Object, runData.ElectricMachinesData.Single().Item2); + var emDict = new Dictionary<PowertrainPosition, IElectricMotorInfo>() { + { PowertrainPosition.BatteryElectricE2, em }, + }; + simplePt.Setup(r => r.ElectricMotorInfo(PowertrainPosition.BatteryElectricE2)) + .Returns(em); + + + simplePt.Setup(r => r.ElectricMotors).Returns(emDict); + + simplePt.Setup(s => s.PowertrainInfo.HasCombustionEngine).Returns(false); + simplePt.Setup(s => s.RunData).Returns(GetRunData(ratios)); + + var testGbx = GetTestGearbox(simplePt.Object, em); + simplePt.Setup(s => s.GearboxCtl).Returns(testGbx.Object); + simplePt.Setup(s => s.GearboxInfo).Returns(testGbx.Object); + simplePt.Setup(s => s.GearboxOutPort).Returns(testGbx.Object); + + simplePt.Setup(s => s.SimulationComponents()).Returns(components); + simplePt.Setup(s => s.Brakes).Returns(new Mock<IBrakes>().Object); + + //Take from real powertrain + simplePt.Setup(s => s.VehicleInfo).Returns(container.Object.VehicleInfo); + simplePt.Setup(s => s.DriverInfo).Returns(container.Object.DriverInfo); + + return simplePt; + } + + Mock<ITestPowertrainTransmission> GetTestGearbox(ISimpleVehicleContainer simpleContainer, ElectricMotor em) + { + Mock<IAMTGearbox> amtGearbox = new Mock<IAMTGearbox>(); + amtGearbox.Name = "PEVAMT_TestGearbox"; + Mock<ITestPowertrainTransmission> gbx = amtGearbox.As<ITestPowertrainTransmission>(); + + + + gbx.Setup(g => g.LastUpshift).Returns(-double.MaxValue.SI<Second>()); + gbx.Setup(g => g.LastDownshift).Returns(-double.MaxValue.SI<Second>()); + + GearshiftPosition gear = null; + gbx.SetupGet(g => g.Gear).Returns(() => { + + return gear; + }); + gbx.SetupSet(g => g.SetGear = It.IsAny<GearshiftPosition>()) + .Callback<GearshiftPosition>(p => { + gear = p; + }); + + + GearshiftPosition nextGear = null; + gbx.SetupGet(g => g.NextGear).Returns(() => nextGear); + gbx.SetupSet(g => g.SetNextGear = It.IsAny<GearshiftPosition>()) + .Callback<GearshiftPosition>(p => nextGear = p); + + gbx.Setup(p => p.Initialize(It.IsAny<NewtonMeter>(), + It.IsAny<PerSecond>())).Returns((NewtonMeter tq, PerSecond rpm) => { + return new ResponseSuccess(this) + { + Engine = { + EngineSpeed = rpm, + PowerRequest = tq * rpm, + }, + }; + }); + gbx.Setup(p => p.Request( + It.IsAny<Second>(), + It.IsAny<Second>(), + It.IsAny<NewtonMeter>(), + It.IsAny<PerSecond>(), + true)).Returns(( + Second absTime, + Second dt, + NewtonMeter t, + PerSecond n, + bool dryRun) => { + + var ratio = + gbx.Object.Gear == null ? 1.0 : ratios[gbx.Object.Gear.Gear].Ratio; + return dryRun + ? new ResponseDryRun(this) { + Engine = { + PowerRequest = n * t, EngineSpeed = n * ratio, + DynamicFullLoadPower = (t / ratio + 2300.SI<NewtonMeter>()) * n * ratio, + TotalTorqueDemand = t, + }, + Clutch = { PowerRequest = n * t }, + DeltaFullLoad = n * t / 2 * (-1) + } + : new ResponseSuccess(this) { + Engine = { + PowerRequest = n * t, + EngineSpeed = n * ratio + + }, + Clutch = { PowerRequest = n * t } + }; + }); + return gbx; + } + + + private VectoRunData GetRunData(double[] ratios) + { + var runData = new VectoRunData(); + + //GearShiftParameters + var gearshiftParameters = new ShiftStrategyParameters() { + TorqueReserve = 0.0, + TimeBetweenGearshifts = 2.SI<Second>(), + DownshiftAfterUpshiftDelay = 2.SI<Second>(), + UpshiftAfterDownshiftDelay = 2.SI<Second>(), + UpshiftMinAcceleration = 0.1.SI<MeterPerSquareSecond>(), + StartSpeed = 0.KMPHtoMeterPerSecond(), + RatingFactorCurrentGear = 1, + AllowedGearRangeFC = 2, + MinEngineSpeedPostUpshift = 0.RPMtoRad(), + }; + runData.GearshiftParameters = gearshiftParameters; + + runData.ElectricMachinesData = GetElectricMachinesData(); + var emData = runData.ElectricMachinesData.Single(i => i.Item1 == PowertrainPosition.BatteryElectricE2) + .Item2; + //VehicleData + var vehicleData = new VehicleData() { + DynamicTyreRadius = 0.492.SI<Meter>(), + }; + runData.VehicleData = vehicleData; + + //CycleData + var mockCycle = new Mock<IDrivingCycleData>(); + mockCycle.Setup(cd => cd.Entries).Returns( + new List<DrivingCycleData.DrivingCycleEntry>() { + new DrivingCycleData.DrivingCycleEntry() { + RoadGradient = 0.SI<Radian>() + } + }); + runData.Cycle = mockCycle.Object; + + + //Gearboxdata + var gearboxInputData = new Mock<IGearboxDeclarationInputData>(); + + var gearsInputData = new List<Mock<ITransmissionInputData>>(); + + gearboxInputData.Setup( + d => d.Gears) + .Returns(gearsInputData.Select(m => m.Object) + .ToList()); + + + var gearboxData = new GearboxData() { + Gears = new Dictionary<uint, GearData>(ratios.Length), + InputData = gearboxInputData.Object, + Type = GearboxType.AMT, + TractionInterruption = 1.SI<Second>(), + Inertia = 0.SI<KilogramSquareMeter>(), + }; + + + + + + runData.GearboxData = gearboxData; + for (uint i = 1; i < ratios.Length; i++) { + gearboxData.Gears[i] = new GearData + { + Ratio = ratios[i], + LossMap = TransmissionLossMapReader.Create(0.96, ratios[i], $"Gear {i}"), + + }; + } + var axlRatio = 3.240355; + var gearsInput = gearboxData.Gears.Select(x => { + var r = new Mock<ITransmissionInputData>(); + r.Setup(g => g.Ratio).Returns(x.Value.Ratio); + r.Setup(g => g.MaxTorque).Returns(x.Value.MaxTorque); + r.Setup(g => g.MaxInputSpeed).Returns(x.Value.MaxSpeed); + + return r.Object; + }).ToList(); + foreach (var entry in gearboxData.Gears) { + var gearIdx = (int)entry.Key - 1; + var dynamicTyreRadius = 0.5.SI<Meter>(); + + var shiftPolygon = DeclarationData.Gearbox.ComputeElectricMotorShiftPolygon( + gearIdx, + emData, + gearsInput); + + entry.Value.ShiftPolygon = shiftPolygon; + + } + + + return runData; + } + + private IList<Tuple<PowertrainPosition, ElectricMotorData>> GetElectricMachinesData() + { + //Nr of electric machines + const int emCount = 2; + //ElectricMachines + // var electricMotorData = new ElectricMotorData() { + // + // }; + var emDataAdapter = new ElectricMachinesDataAdapter(); + var emInputData = new Mock<IElectricMotorDeclarationInputData>(); + + var powerMapMock = new Mock<IElectricMotorPowerMap>(); + powerMapMock.Setup(pm => pm.Gear).Returns(0); + powerMapMock.Setup(pm => pm.PowerMap).Returns(GetEfficiencyMapData()); + + var voltageLevels = new List<IElectricMotorVoltageLevel>() { + new ElectricMotorVoltageLevel(){ + VoltageLevel = 100.SI<Volt>(), + ContinuousTorque = 450.SI<NewtonMeter>(), + ContinuousTorqueSpeed = 2460.RPMtoRad(), + OverloadTorque = 485.SI<NewtonMeter>(), + OverloadTestSpeed = 2460.RPMtoRad(), + OverloadTime = 120.SI<Second>(), + FullLoadCurve = GetFullLoadCurveData(), + PowerMap = new List<IElectricMotorPowerMap>(){powerMapMock.Object} + }, + new ElectricMotorVoltageLevel(){ + VoltageLevel = 1000.SI<Volt>(), + ContinuousTorque = 450.SI<NewtonMeter>(), + ContinuousTorqueSpeed = 2460.RPMtoRad(), + OverloadTorque = 485.SI<NewtonMeter>(), + OverloadTestSpeed = 2460.RPMtoRad(), + OverloadTime = 120.SI<Second>(), + FullLoadCurve = GetFullLoadCurveData(), + PowerMap = new List<IElectricMotorPowerMap>(){powerMapMock.Object} + } + }; + + emInputData.Setup(em => em.CertificationMethod).Returns(CertificationMethod.Measured); + emInputData.Setup(em => em.Inertia).Returns(0.225.SI<KilogramSquareMeter>()); + emInputData.Setup(em => em.R85RatedPower).Returns(250E3.SI<Watt>()); + emInputData.Setup(em => em.ElectricMachineType).Returns(ElectricMachineType.ASM); + emInputData.Setup(em => em.VoltageLevels).Returns(voltageLevels); + emInputData.Setup(em => em.DragCurve).Returns(GetDragCurveData); + + var adcInputData = new Mock<IADCDeclarationInputData>(); + adcInputData.Setup(adc => adc.Ratio).Returns(1.0f); + + var emsInputData = new Mock<IElectricMachinesDeclarationInputData>(); + emsInputData.Setup(em => em.Entries).Returns( + new List<ElectricMachineEntry<IElectricMotorDeclarationInputData>>() { + new ElectricMachineEntry<IElectricMotorDeclarationInputData>() { + Count = emCount, + Position = PowertrainPosition.BatteryElectricE2, + ElectricMachine = emInputData.Object, + ADC = adcInputData.Object, + RatioADC = 2.0, + MechanicalTransmissionEfficiency = 0.97, + } + }); + + var avgVoltage = 200.SI<Volt>(); + IDictionary<PowertrainPosition, IList<Tuple<Volt, TableData>>> torqueLimits = new Dictionary<PowertrainPosition, IList<Tuple<Volt, TableData>>>(); + + var electricMachinesData = emDataAdapter.CreateElectricMachines(emsInputData.Object, torqueLimits:torqueLimits, + avgVoltage, null); + + + + + + return electricMachinesData; + + } + + private TableData GetDragCurveData() + { + return InputDataHelper.InputDataAsTableData( + "n [rpm] , T_drag [Nm]", + "0 , -6.06", + "7363.77 , -30.31"); + } + + + private TableData GetFullLoadCurveData() + { + return InputDataHelper.InputDataAsTableData("n [rpm] , T_drive [Nm] , T_drag [Nm]", + #region data + "0,485,-485", +"2461.158914,485,-485", +"2452.135493,485,-485", +"2466.863034,483.8845,-483.8845", +"2481.590574,481.010875,-481.010875", +"2496.318115,478.173625,-478.173625", +"2503.681885,476.767125,-476.767125", +"2577.319588,463.138625,-463.138625", +"2650.95729,450.274,-450.274", +"2724.594993,438.1005,-438.1005", +"2798.232695,426.58175,-426.58175", +"2871.870398,415.645,-415.645", +"2945.5081,405.253875,-405.253875", +"3019.145803,395.359875,-395.359875", +"3092.783505,385.950875,-385.950875", +"3166.421208,376.978375,-376.978375", +"3240.05891,368.406,-368.406", +"3313.696613,360.221625,-360.221625", +"3387.334315,352.388875,-352.388875", +"3460.972018,344.895625,-344.895625", +"3534.60972,337.7055,-337.7055", +"3608.247423,330.8185,-330.8185", +"3681.885125,324.19825,-324.19825", +"3755.522828,317.84475,-317.84475", +"3829.16053,311.73375,-311.73375", +"3902.798233,305.853125,-305.853125", +"3976.435935,300.178625,-300.178625", +"4050.073638,294.722375,-294.722375", +"4123.71134,289.460125,-289.460125", +"4197.349043,284.37975,-284.37975", +"4270.986745,279.48125,-279.48125", +"4344.624448,274.740375,-274.740375", +"4418.26215,270.16925,-270.16925", +"4491.899853,265.7315,-265.7315", +"4565.537555,261.451375,-261.451375", +"4639.175258,257.304625,-257.304625", +"4712.81296,253.279125,-253.279125", +"4786.450663,249.387,-249.387", +"4860.088365,245.604,-245.604", +"4933.726068,241.94225,-241.94225", +"5007.36377,238.3775,-238.3775", +"5081.001473,234.921875,-234.921875", +"5154.639175,231.575375,-231.575375", +"5228.276878,228.31375,-228.31375", +"5301.91458,225.137,-225.137", +"5375.552283,222.05725,-222.05725", +"5449.189985,219.05025,-219.05025", +"5522.827688,216.128125,-216.128125", +"5596.46539,213.290875,-213.290875", +"5670.103093,210.51425,-210.51425", +"5743.740795,207.8225,-207.8225", +"5817.378498,205.191375,-205.191375", +"5891.0162,202.620875,-202.620875", +"5964.653903,200.123125,-200.123125", +"6038.291605,197.686,-197.686", +"6111.929308,195.297375,-195.297375", +"6185.56701,192.969375,-192.969375", +"6259.204713,190.702,-190.702", +"6332.842415,188.483125,-188.483125", +"6406.480118,186.324875,-186.324875", +"6480.11782,184.203,-184.203", +"6553.755523,182.129625,-182.129625", +"6627.393225,180.10475,-180.10475", +"6701.030928,178.128375,-178.128375", +"6774.66863,176.2005,-176.2005", +"6848.306333,174.296875,-174.296875", +"6921.944035,172.44175,-172.44175", +"6995.581738,170.635125,-170.635125", +"7069.21944,168.85275,-168.85275", +"7142.857143,167.10675,-167.10675", +"7216.494845,165.40925,-165.40925", +"7290.132548,163.736,-163.736", +"7363.77025,162.099125,-162.099125" + #endregion data + ); + } + private ElectricMotorFullLoadCurve GetFullLoadCurve(int count) + { + var inputData = GetFullLoadCurveData(); + return ElectricFullLoadCurveReader.Create(inputData, count); + } + private TableData GetEfficiencyMapData() + { + return InputDataHelper.InputDataAsTableData( + "n [rpm] , T [Nm] , P_el [kW]", + #region entries + "0, -485, 0.000", +"0, -461, 0.000", +"0, -437, 0.000", +"0, -412, 0.000", +"0, -388, 0.000", +"0, -364, 0.000", +"0, -340, 0.000", +"0, -315, 0.000", +"0, -291, 0.000", +"0, -267, 0.000", +"0, -243, 0.000", +"0, -218, 0.000", +"0, -194, 0.000", +"0, -170, 0.000", +"0, -146, 0.000", +"0, -121, 0.000", +"0, -97, 0.000", +"0, -73, 0.000", +"0, -48, 0.000", +"0, -24, 0.000", +"0, -5, 0.000", +"0, 5, 0.000", +"0, 24, 0.000", +"0, 48, 0.000", +"0, 73, 0.000", +"0, 97, 0.000", +"0, 121, 0.000", +"0, 146, 0.000", +"0, 170, 0.000", +"0, 194, 0.000", +"0, 218, 0.000", +"0, 243, 0.000", +"0, 267, 0.000", +"0, 291, 0.000", +"0, 315, 0.000", +"0, 340, 0.000", +"0, 364, 0.000", +"0, 388, 0.000", +"0, 412, 0.000", +"0, 437, 0.000", +"0, 461, 0.000", +"0, 485, 0.000", +"49, -485, 0.000", +"49, -461, 0.000", +"49, -437, 0.000", +"49, -412, 0.000", +"49, -388, 0.000", +"49, -364, 0.000", +"49, -340, -0.045", +"49, -315, -0.111", +"49, -291, -0.166", +"49, -267, -0.211", +"49, -243, -0.245", +"49, -218, -0.268", +"49, -194, -0.280", +"49, -170, -0.281", +"49, -146, -0.272", +"49, -121, -0.252", +"49, -97, -0.221", +"49, -73, -0.179", +"49, -48, -0.126", +"49, -24, -0.062", +"49, -5, -0.004", +"49, 5, 0.048", +"49, 24, 0.193", +"49, 48, 0.384", +"49, 73, 0.587", +"49, 97, 0.802", +"49, 121, 1.029", +"49, 146, 1.267", +"49, 170, 1.518", +"49, 194, 1.779", +"49, 218, 2.053", +"49, 243, 2.338", +"49, 267, 2.636", +"49, 291, 2.944", +"49, 315, 3.265", +"49, 340, 3.597", +"49, 364, 3.941", +"49, 388, 4.297", +"49, 412, 4.665", +"49, 437, 5.044", +"49, 461, 5.435", +"49, 485, 5.838", +"492, -485, -20.733", +"492, -461, -19.800", +"492, -437, -18.856", +"492, -412, -17.900", +"492, -388, -16.932", +"492, -364, -15.953", +"492, -340, -14.962", +"492, -315, -13.959", +"492, -291, -12.945", +"492, -267, -11.919", +"492, -243, -10.881", +"492, -218, -9.832", +"492, -194, -8.771", +"492, -170, -7.699", +"492, -146, -6.614", +"492, -121, -5.519", +"492, -97, -4.411", +"492, -73, -3.292", +"492, -48, -2.161", +"492, -24, -1.019", +"492, -5, -0.097", +"492, 5, 0.416", +"492, 24, 1.498", +"492, 48, 2.863", +"492, 73, 4.240", +"492, 97, 5.630", +"492, 121, 7.033", +"492, 146, 8.448", +"492, 170, 9.876", +"492, 194, 11.316", +"492, 218, 12.769", +"492, 243, 14.235", +"492, 267, 15.713", +"492, 291, 17.204", +"492, 315, 18.708", +"492, 340, 20.224", +"492, 364, 21.753", +"492, 388, 23.294", +"492, 412, 24.848", +"492, 437, 26.415", +"492, 461, 27.994", +"492, 485, 29.586", +"984, -485, -44.101", +"984, -461, -42.013", +"984, -437, -39.910", +"984, -412, -37.794", +"984, -388, -35.664", +"984, -364, -33.520", +"984, -340, -31.362", +"984, -315, -29.190", +"984, -291, -27.004", +"984, -267, -24.805", +"984, -243, -22.591", +"984, -218, -20.363", +"984, -194, -18.122", +"984, -170, -15.867", +"984, -146, -13.597", +"984, -121, -11.314", +"984, -97, -9.017", +"984, -73, -6.706", +"984, -48, -4.381", +"984, -24, -2.042", +"984, -5, -0.161", +"984, 5, 0.867", +"984, 24, 2.993", +"984, 48, 5.663", +"984, 73, 8.349", +"984, 97, 11.049", +"984, 121, 13.765", +"984, 146, 16.496", +"984, 170, 19.242", +"984, 194, 22.003", +"984, 218, 24.779", +"984, 243, 27.571", +"984, 267, 30.377", +"984, 291, 33.198", +"984, 315, 36.035", +"984, 340, 38.887", +"984, 364, 41.754", +"984, 388, 44.635", +"984, 412, 47.532", +"984, 437, 50.445", +"984, 461, 53.372", +"984, 485, 56.314", +"1477, -485, -67.122", +"1477, -461, -63.906", +"1477, -437, -60.673", +"1477, -412, -57.422", +"1477, -388, -54.153", +"1477, -364, -50.867", +"1477, -340, -47.563", +"1477, -315, -44.241", +"1477, -291, -40.902", +"1477, -267, -37.545", +"1477, -243, -34.170", +"1477, -218, -30.778", +"1477, -194, -27.368", +"1477, -170, -23.941", +"1477, -146, -20.496", +"1477, -121, -17.033", +"1477, -97, -13.552", +"1477, -73, -10.054", +"1477, -48, -6.539", +"1477, -24, -3.005", +"1477, -5, -0.166", +"1477, 5, 1.383", +"1477, 24, 4.552", +"1477, 48, 8.530", +"1477, 73, 12.528", +"1477, 97, 16.545", +"1477, 121, 20.581", +"1477, 146, 24.636", +"1477, 170, 28.710", +"1477, 194, 32.804", +"1477, 218, 36.916", +"1477, 243, 41.048", +"1477, 267, 45.199", +"1477, 291, 49.369", +"1477, 315, 53.558", +"1477, 340, 57.766", +"1477, 364, 61.994", +"1477, 388, 66.240", +"1477, 412, 70.506", +"1477, 437, 74.791", +"1477, 461, 79.095", +"1477, 485, 83.418", +"1969, -485, -89.780", +"1969, -461, -85.464", +"1969, -437, -81.126", +"1969, -412, -76.766", +"1969, -388, -72.382", +"1969, -364, -67.976", +"1969, -340, -63.546", +"1969, -315, -59.094", +"1969, -291, -54.620", +"1969, -267, -50.122", +"1969, -243, -45.602", +"1969, -218, -41.058", +"1969, -194, -36.492", +"1969, -170, -31.904", +"1969, -146, -27.292", +"1969, -121, -22.658", +"1969, -97, -18.000", +"1969, -73, -13.320", +"1969, -48, -8.618", +"1969, -24, -3.892", +"1969, -5, -0.095", +"1969, 5, 1.980", +"1969, 24, 6.193", +"1969, 48, 11.483", +"1969, 73, 16.796", +"1969, 97, 22.135", +"1969, 121, 27.498", +"1969, 146, 32.886", +"1969, 170, 38.299", +"1969, 194, 43.736", +"1969, 218, 49.199", +"1969, 243, 54.686", +"1969, 267, 60.197", +"1969, 291, 65.734", +"1969, 315, 71.295", +"1969, 340, 76.881", +"1969, 364, 82.492", +"1969, 388, 88.127", +"1969, 412, 93.787", +"1969, 437, 99.472", +"1969, 461, 105.182", +"1969, 485, 110.916", +"2461, -485, -112.056", +"2461, -461, -106.670", +"2461, -437, -101.254", +"2461, -412, -95.808", +"2461, -388, -90.334", +"2461, -364, -84.830", +"2461, -340, -79.296", +"2461, -315, -73.733", +"2461, -291, -68.141", +"2461, -267, -62.519", +"2461, -243, -56.868", +"2461, -218, -51.188", +"2461, -194, -45.478", +"2461, -170, -39.738", +"2461, -146, -33.970", +"2461, -121, -28.172", +"2461, -97, -22.344", +"2461, -73, -16.487", +"2461, -48, -10.601", +"2461, -24, -4.685", +"2461, -5, 0.000", +"2461, 5, 2.679", +"2461, 24, 7.937", +"2461, 48, 14.539", +"2461, 73, 21.173", +"2461, 97, 27.839", +"2461, 121, 34.536", +"2461, 146, 41.266", +"2461, 170, 48.027", +"2461, 194, 54.820", +"2461, 218, 61.646", +"2461, 243, 68.503", +"2461, 267, 75.392", +"2461, 291, 82.313", +"2461, 315, 89.265", +"2461, 340, 96.250", +"2461, 364, 103.267", +"2461, 388, 110.315", +"2461, 412, 117.396", +"2461, 437, 124.508", +"2461, 461, 131.652", +"2461, 485, 138.828", +"2953, -485, -133.934", +"2953, -461, -127.504", +"2953, -437, -121.037", +"2953, -412, -114.532", +"2953, -388, -107.990", +"2953, -364, -101.411", +"2953, -340, -94.794", +"2953, -315, -88.140", +"2953, -291, -81.448", +"2953, -267, -74.719", +"2953, -243, -67.952", +"2953, -218, -61.148", +"2953, -194, -54.306", +"2953, -170, -47.427", +"2953, -146, -40.511", +"2953, -121, -33.557", +"2953, -97, -26.566", +"2953, -73, -19.537", +"2953, -48, -12.471", +"2953, -24, -5.367", +"2953, -5, 0.000", +"2953, 5, 3.497", +"2953, 24, 9.801", +"2953, 48, 17.718", +"2953, 73, 25.676", +"2953, 97, 33.674", +"2953, 121, 41.713", +"2953, 146, 49.793", +"2953, 170, 57.913", +"2953, 194, 66.074", +"2953, 218, 74.275", +"2953, 243, 82.517", +"2953, 267, 90.800", +"2953, 291, 99.123", +"2953, 315, 107.487", +"2953, 340, 115.892", +"2953, 364, 124.337", +"2953, 388, 132.823", +"2953, 412, 141.349", +"2953, 437, 149.916", +"2953, 461, 158.524", +"2953, 485, 167.172", +"3446, -485, -155.396", +"3446, -461, -147.951", +"3446, -437, -140.460", +"3446, -412, -132.921", +"3446, -388, -125.335", +"3446, -364, -117.703", +"3446, -340, -110.023", +"3446, -315, -102.297", +"3446, -291, -94.524", +"3446, -267, -86.703", +"3446, -243, -78.836", +"3446, -218, -70.922", +"3446, -194, -62.961", +"3446, -170, -54.953", +"3446, -146, -46.898", +"3446, -121, -38.797", +"3446, -97, -30.648", +"3446, -73, -22.452", +"3446, -48, -14.210", +"3446, -24, -5.921", +"3446, -5, 0.000", +"3446, 5, 4.454", +"3446, 24, 11.805", +"3446, 48, 21.040", +"3446, 73, 30.325", +"3446, 97, 39.661", +"3446, 121, 49.049", +"3446, 146, 58.487", +"3446, 170, 67.976", +"3446, 194, 77.516", +"3446, 218, 87.107", +"3446, 243, 96.749", +"3446, 267, 106.442", +"3446, 291, 116.185", +"3446, 315, 125.980", +"3446, 340, 135.826", +"3446, 364, 145.722", +"3446, 388, 155.669", +"3446, 412, 165.668", +"3446, 437, 175.717", +"3446, 461, 185.817", +"3446, 485, 195.968", +"3938, -485, -176.425", +"3938, -461, -167.994", +"3938, -437, -159.504", +"3938, -412, -150.956", +"3938, -388, -142.351", +"3938, -364, -133.687", +"3938, -340, -124.966", +"3938, -315, -116.187", +"3938, -291, -107.351", +"3938, -267, -98.456", +"3938, -243, -89.503", +"3938, -218, -80.493", +"3938, -194, -71.425", +"3938, -170, -62.299", +"3938, -146, -53.115", +"3938, -121, -43.873", +"3938, -97, -34.574", +"3938, -73, -25.217", +"3938, -48, -15.801", +"3938, -24, -6.328", +"3938, -5, 0.000", +"3938, 5, 5.568", +"3938, 24, 13.967", +"3938, 48, 24.521", +"3938, 73, 35.138", +"3938, 97, 45.818", +"3938, 121, 56.561", +"3938, 146, 67.366", +"3938, 170, 78.235", +"3938, 194, 89.166", +"3938, 218, 100.159", +"3938, 243, 111.216", +"3938, 267, 122.335", +"3938, 291, 133.517", +"3938, 315, 144.762", +"3938, 340, 156.070", +"3938, 364, 167.440", +"3938, 388, 178.873", +"3938, 412, 190.369", +"3938, 437, 201.927", +"3938, 461, 213.549", +"3938, 485, 225.233", +"4430, -485, -197.004", +"4430, -461, -187.614", +"4430, -437, -178.152", +"4430, -412, -168.621", +"4430, -388, -159.020", +"4430, -364, -149.348", +"4430, -340, -139.606", +"4430, -315, -129.794", +"4430, -291, -119.912", +"4430, -267, -109.959", +"4430, -243, -99.936", +"4430, -218, -89.844", +"4430, -194, -79.680", +"4430, -170, -69.447", +"4430, -146, -59.144", +"4430, -121, -48.770", +"4430, -97, -38.326", +"4430, -73, -27.812", +"4430, -48, -17.228", +"4430, -24, -6.573", +"4430, -5, 0.000", +"4430, 5, 6.859", +"4430, 24, 16.305", +"4430, 48, 28.182", +"4430, 73, 40.135", +"4430, 97, 52.164", +"4430, 121, 64.269", +"4430, 146, 76.450", +"4430, 170, 88.707", +"4430, 194, 101.041", +"4430, 218, 113.451", +"4430, 243, 125.937", +"4430, 267, 138.499", +"4430, 291, 151.138", +"4430, 315, 163.852", +"4430, 340, 176.643", +"4430, 364, 189.510", +"4430, 388, 202.453", +"4430, 412, 215.472", +"4430, 437, 228.567", +"4430, 461, 241.739", +"4430, 485, 254.986", +"4922, -485, -217.116", +"4922, -461, -206.794", +"4922, -437, -196.388", +"4922, -412, -185.899", +"4922, -388, -175.325", +"4922, -364, -164.667", +"4922, -340, -153.925", +"4922, -315, -143.099", +"4922, -291, -132.190", +"4922, -267, -121.196", +"4922, -243, -110.118", +"4922, -218, -98.956", +"4922, -194, -87.710", +"4922, -170, -76.381", +"4922, -146, -64.967", +"4922, -121, -53.469", +"4922, -97, -41.887", +"4922, -73, -30.221", +"4922, -48, -18.472", +"4922, -24, -6.638", +"4922, -5, 0.000", +"4922, 5, 8.344", +"4922, 24, 18.839", +"4922, 48, 32.040", +"4922, 73, 45.333", +"4922, 97, 58.716", +"4922, 121, 72.191", +"4922, 146, 85.757", +"4922, 170, 99.413", +"4922, 194, 113.161", +"4922, 218, 127.001", +"4922, 243, 140.931", +"4922, 267, 154.952", +"4922, 291, 169.065", +"4922, 315, 183.269", +"4922, 340, 197.564", +"4922, 364, 211.950", +"4922, 388, 226.427", +"4922, 412, 240.995", +"4922, 437, 255.655", +"4922, 461, 270.406", +"4922, 485, 285.247", +"5415, -485, -236.743", +"5415, -461, -225.518", +"5415, -437, -214.194", +"5415, -412, -202.771", +"5415, -388, -191.249", +"5415, -364, -179.627", +"5415, -340, -167.906", +"5415, -315, -156.086", +"5415, -291, -144.167", +"5415, -267, -132.149", +"5415, -243, -120.031", +"5415, -218, -107.814", +"5415, -194, -95.497", +"5415, -170, -83.082", +"5415, -146, -70.567", +"5415, -121, -57.953", +"5415, -97, -45.240", +"5415, -73, -32.428", +"5415, -48, -19.516", +"5415, -24, -6.505", +"5415, -5, 0.000", +"5415, 5, 10.043", +"5415, 24, 21.588", +"5415, 48, 36.116", +"5415, 73, 50.751", +"5415, 97, 65.495", +"5415, 121, 80.346", +"5415, 146, 95.305", +"5415, 170, 110.371", +"5415, 194, 125.545", +"5415, 218, 140.827", +"5415, 243, 156.217", +"5415, 267, 171.714", +"5415, 291, 187.319", +"5415, 315, 203.031", +"5415, 340, 218.852", +"5415, 364, 234.779", +"5415, 388, 250.815", +"5415, 412, 266.958", +"5415, 437, 283.209", +"5415, 461, 299.568", +"5415, 485, 316.034", +"5907, -485, -255.867", +"5907, -461, -243.768", +"5907, -437, -231.553", +"5907, -412, -219.222", +"5907, -388, -206.774", +"5907, -364, -194.211", +"5907, -340, -181.532", +"5907, -315, -168.738", +"5907, -291, -155.827", +"5907, -267, -142.800", +"5907, -243, -129.657", +"5907, -218, -116.399", +"5907, -194, -103.024", +"5907, -170, -89.534", +"5907, -146, -75.928", +"5907, -121, -62.205", +"5907, -97, -48.367", +"5907, -73, -34.413", +"5907, -48, -20.343", +"5907, -24, -6.157", +"5907, -5, 0.000", +"5907, 5, 11.974", +"5907, 24, 24.569", +"5907, 48, 40.426", +"5907, 73, 56.409", +"5907, 97, 72.518", +"5907, 121, 88.753", +"5907, 146, 105.113", +"5907, 170, 121.599", +"5907, 194, 138.211", +"5907, 218, 154.949", +"5907, 243, 171.813", +"5907, 267, 188.802", +"5907, 291, 205.917", +"5907, 315, 223.158", +"5907, 340, 240.525", +"5907, 364, 258.017", +"5907, 388, 275.635", +"5907, 412, 293.379", +"5907, 437, 311.249", +"5907, 461, 329.245", +"5907, 485, 347.366", +"6399, -485, -274.473", +"6399, -461, -261.527", +"6399, -437, -248.447", +"6399, -412, -235.232", +"6399, -388, -221.884", +"6399, -364, -208.402", +"6399, -340, -194.786", +"6399, -315, -181.036", +"6399, -291, -167.151", +"6399, -267, -153.133", +"6399, -243, -138.981", +"6399, -218, -124.694", +"6399, -194, -110.274", +"6399, -170, -95.719", +"6399, -146, -81.031", +"6399, -121, -66.208", +"6399, -97, -51.252", +"6399, -73, -36.161", +"6399, -48, -20.936", +"6399, -24, -5.577", +"6399, -5, 0.000", +"6399, 5, 14.156", +"6399, 24, 27.802", +"6399, 48, 44.991", +"6399, 73, 62.325", +"6399, 97, 79.805", +"6399, 121, 97.430", +"6399, 146, 115.201", +"6399, 170, 133.117", +"6399, 194, 151.179", +"6399, 218, 169.386", +"6399, 243, 187.738", +"6399, 267, 206.236", +"6399, 291, 224.879", +"6399, 315, 243.668", +"6399, 340, 262.602", +"6399, 364, 281.682", +"6399, 388, 300.907", +"6399, 412, 320.277", +"6399, 437, 339.793", +"6399, 461, 359.455", +"6399, 485, 379.261", +"6891, -485, -292.541", +"6891, -461, -278.777", +"6891, -437, -264.858", +"6891, -412, -250.787", +"6891, -388, -236.561", +"6891, -364, -222.182", +"6891, -340, -207.650", +"6891, -315, -192.963", +"6891, -291, -178.124", +"6891, -267, -163.130", +"6891, -243, -147.983", +"6891, -218, -132.683", +"6891, -194, -117.228", +"6891, -170, -101.621", +"6891, -146, -85.859", +"6891, -121, -69.944", +"6891, -97, -53.876", +"6891, -73, -37.653", +"6891, -48, -21.278", +"6891, -24, -4.748", +"6891, -5, 0.000", +"6891, 5, 16.608", +"6891, 24, 31.306", +"6891, 48, 49.829", +"6891, 73, 68.518", +"6891, 97, 87.374", +"6891, 121, 106.397", +"6891, 146, 125.587", +"6891, 170, 144.943", +"6891, 194, 164.466", +"6891, 218, 184.155", +"6891, 243, 204.011", +"6891, 267, 224.034", +"6891, 291, 244.223", +"6891, 315, 264.580", +"6891, 340, 285.102", +"6891, 364, 305.792", +"6891, 388, 326.648", +"6891, 412, 347.671", +"6891, 437, 368.860", +"6891, 461, 390.216", +"6891, 485, 411.739", +"7383, -485, -310.056", +"7383, -461, -295.501", +"7383, -437, -280.771", +"7383, -412, -265.867", +"7383, -388, -250.788", +"7383, -364, -235.535", +"7383, -340, -220.106", +"7383, -315, -204.504", +"7383, -291, -188.726", +"7383, -267, -172.775", +"7383, -243, -156.648", +"7383, -218, -140.347", +"7383, -194, -123.871", +"7383, -170, -107.221", +"7383, -146, -90.396", +"7383, -121, -73.397", +"7383, -97, -56.222", +"7383, -73, -38.874", +"7383, -48, -21.350", +"7383, -24, -3.653", +"7383, -5, 0.000", +"7383, 5, 19.348", +"7383, 24, 35.099", +"7383, 48, 54.958", +"7383, 73, 75.007", +"7383, 97, 95.245", +"7383, 121, 115.672", +"7383, 146, 136.289", +"7383, 170, 157.095", +"7383, 194, 178.091", +"7383, 218, 199.276", +"7383, 243, 220.651", +"7383, 267, 242.215", +"7383, 291, 263.969", +"7383, 315, 285.912", +"7383, 340, 308.044", +"7383, 364, 330.366", +"7383, 388, 352.878", +"7383, 412, 375.578", +"7383, 437, 398.469", +"7383, 461, 421.549", +"7383, 485, 444.818", +"7876, -485, -327.000", +"7876, -461, -311.682", +"7876, -437, -296.167", +"7876, -412, -280.456", +"7876, -388, -264.547", +"7876, -364, -248.442", +"7876, -340, -232.139", +"7876, -315, -215.639", +"7876, -291, -198.942", +"7876, -267, -182.048", +"7876, -243, -164.958", +"7876, -218, -147.670", +"7876, -194, -130.185", +"7876, -170, -112.503", +"7876, -146, -94.624", +"7876, -121, -76.548", +"7876, -97, -58.274", +"7876, -73, -39.804", +"7876, -48, -21.137", +"7876, -24, -2.273", +"7876, -5, 0.000", +"7876, 5, 22.396", +"7876, 24, 39.201", +"7876, 48, 60.398", +"7876, 73, 81.810", +"7876, 97, 103.435", +"7876, 121, 125.274", +"7876, 146, 147.327", +"7876, 170, 169.593", +"7876, 194, 192.074", +"7876, 218, 214.768", +"7876, 243, 237.676", +"7876, 267, 260.798", +"7876, 291, 284.134", +"7876, 315, 307.683", +"7876, 340, 331.447", +"7876, 364, 355.424", +"7876, 388, 379.615", +"7876, 412, 404.019", +"7876, 437, 428.638", +"7876, 461, 453.470", +"7876, 485, 478.516", +"8368, -485, -343.355", +"8368, -461, -327.303", +"8368, -437, -311.030", +"8368, -412, -294.536", +"8368, -388, -277.822", +"8368, -364, -260.886", +"8368, -340, -243.730", +"8368, -315, -226.352", +"8368, -291, -208.754", +"8368, -267, -190.935", +"8368, -243, -172.895", +"8368, -218, -154.634", +"8368, -194, -136.152", +"8368, -170, -117.449", +"8368, -146, -98.525", +"8368, -121, -79.380", +"8368, -97, -60.014", +"8368, -73, -40.428", +"8368, -48, -20.620", +"8368, -24, -0.592", +"8368, -5, 0.000", +"8368, 5, 25.770", +"8368, 24, 43.629", +"8368, 48, 66.167", +"8368, 73, 88.946", +"8368, 97, 111.964", +"8368, 121, 135.221", +"8368, 146, 158.719", +"8368, 170, 182.456", +"8368, 194, 206.433", +"8368, 218, 230.649", +"8368, 243, 255.106", +"8368, 267, 279.802", +"8368, 291, 304.738", +"8368, 315, 329.913", +"8368, 340, 355.328", +"8368, 364, 380.983", +"8368, 388, 406.878", +"8368, 412, 433.012", +"8368, 437, 459.386", +"8368, 461, 486.000", +"8368, 485, 512.853", +"8860, -485, -359.104", +"8860, -461, -342.346", +"8860, -437, -325.341", +"8860, -412, -308.091", +"8860, -388, -290.594", +"8860, -364, -272.851", +"8860, -340, -254.862", +"8860, -315, -236.626", +"8860, -291, -218.144", +"8860, -267, -199.416", +"8860, -243, -180.442", +"8860, -218, -161.221", +"8860, -194, -141.755", +"8860, -170, -122.042", +"8860, -146, -102.082", +"8860, -121, -81.877", +"8860, -97, -61.425", +"8860, -73, -40.727", +"8860, -48, -19.783", +"8860, -24, 0.000", +"8860, -5, 0.000", +"8860, 5, 29.489", +"8860, 24, 48.402", +"8860, 48, 72.284", +"8860, 73, 96.433", +"8860, 97, 120.849", +"8860, 121, 145.533", +"8860, 146, 170.484", +"8860, 170, 195.701", +"8860, 194, 221.186", +"8860, 218, 246.939", +"8860, 243, 272.958", +"8860, 267, 299.245", +"8860, 291, 325.798", +"8860, 315, 352.619", +"8860, 340, 379.708", +"8860, 364, 407.063", +"8860, 388, 434.685", +"8860, 412, 462.575", +"8860, 437, 490.732", +"8860, 461, 519.156", +"8860, 485, 547.847", +"9352, -485, -374.230", +"9352, -461, -356.794", +"9352, -437, -339.084", +"9352, -412, -321.102", +"9352, -388, -302.847", +"9352, -364, -284.319", +"9352, -340, -265.517", +"9352, -315, -246.443", +"9352, -291, -227.096", +"9352, -267, -207.475", +"9352, -243, -187.582", +"9352, -218, -167.416", +"9352, -194, -146.976", +"9352, -170, -126.264", +"9352, -146, -105.279", +"9352, -121, -84.021", +"9352, -97, -62.489", +"9352, -73, -40.685", +"9352, -48, -18.608", +"9352, -24, 0.000", +"9352, -5, 0.000", +"9352, 5, 33.571", +"9352, 24, 53.540", +"9352, 48, 78.768", +"9352, 73, 104.291", +"9352, 97, 130.111", +"9352, 121, 156.228", +"9352, 146, 182.640", +"9352, 170, 209.349", +"9352, 194, 236.354", +"9352, 218, 263.655", +"9352, 243, 291.252", +"9352, 267, 319.146", +"9352, 291, 347.335", +"9352, 315, 375.821", +"9352, 340, 404.604", +"9352, 364, 433.682", +"9352, 388, 463.057", +"9352, 412, 492.728", +"9352, 437, 522.695", +"9352, 461, 552.958", +"9352, 485, 583.518", +"9845, -485, -388.716", +"9845, -461, -370.630", +"9845, -437, -352.242", +"9845, -412, -333.553", +"9845, -388, -314.563", +"9845, -364, -295.272", +"9845, -340, -275.680", +"9845, -315, -255.786", +"9845, -291, -235.591", +"9845, -267, -215.095", +"9845, -243, -194.298", +"9845, -218, -173.200", +"9845, -194, -151.800", +"9845, -170, -130.099", +"9845, -146, -108.097", +"9845, -121, -85.794", +"9845, -97, -63.190", +"9845, -73, -40.284", +"9845, -48, -17.077", +"9845, -24, 0.000", +"9845, -5, 0.000", +"9845, 5, 38.036", +"9845, 24, 59.061", +"9845, 48, 85.637", +"9845, 73, 112.539", +"9845, 97, 139.768", +"9845, 121, 167.324", +"9845, 146, 195.207", +"9845, 170, 223.417", +"9845, 194, 251.953", +"9845, 218, 280.816", +"9845, 243, 310.007", +"9845, 267, 339.523", +"9845, 291, 369.367", +"9845, 315, 399.538", +"9845, 340, 430.035", +"9845, 364, 460.859", +"9845, 388, 492.010", +"9845, 412, 523.488", +"9845, 437, 555.293", +"9845, 461, 587.424", +"9845, 485, 619.883" + #endregion data + ).ApplyFactor(ElectricMotorMapReader.Fields.PowerElectrical, 1E3); //Convert from kW to W + } + + private EfficiencyMap GetEfficiencyMap(int count) + { + return ElectricMotorMapReader.Create(GetEfficiencyMapData(), count, ExecutionMode.Declaration); + } + private void SetVelocityDropLookupData(PEVAMTShiftStrategy shiftStrategy) + { + //"StartVelocity [km/h], Gradient [-], EndVelocity [km/h]" + var data = new[] { + new[] { 5.0, -0.0997, 9.061522965237558 }, + new[] { 5.0, -0.0798, 7.76698080079411 }, + new[] { 5.0, -0.0599, 6.46583777913701 }, + new[] { 5.0, -0.0400, 5.1596021788785045 }, + new[] { 5.0, -0.0200, 3.8498121019126907 }, + new[] { 5.0, 0.0000, 2.5380265159468918 }, + new[] { 5.0, 0.0200, 1.2258160477557427 }, + new[] { 5.0, 0.0400, 0.0 }, + new[] { 5.0, 0.0599, 0.0 }, + new[] { 5.0, 0.0798, 0.0 }, + new[] { 5.0, 0.0997, 0.0 }, + new[] { 10.0, -0.0997, 14.807789640888302 }, + new[] { 10.0, -0.0798, 13.474253785811362 }, + new[] { 10.0, -0.0599, 12.133880027250777 }, + new[] { 10.0, -0.0400, 10.788221550084467 }, + new[] { 10.0, -0.0200, 9.438862432338068 }, + new[] { 10.0, 0.0000, 8.087408432114643 }, + new[] { 10.0, 0.0200, 6.735477499784416 }, + new[] { 10.0, 0.0400, 5.384690105076845 }, + new[] { 10.0, 0.0599, 4.036659549786269 }, + new[] { 10.0, 0.0798, 2.6929823705748137 }, + new[] { 10.0, 0.0997, 1.3552289800549435 }, + new[] { 20.0, -0.0997, 25.061542153872097 }, + new[] { 20.0, -0.0798, 23.72002987685605 }, + new[] { 20.0, -0.0599, 22.371630788642932 }, + new[] { 20.0, -0.0400, 21.017907257116025 }, + new[] { 20.0, -0.0200, 19.660452757813403 }, + new[] { 20.0, 0.0000, 18.30088261992287 }, + new[] { 20.0, 0.0200, 16.94082447048767 }, + new[] { 20.0, 0.0400, 15.581908518759507 }, + new[] { 20.0, 0.0599, 14.225757795590708 }, + new[] { 20.0, 0.0798, 12.873978508374211 }, + new[] { 20.0, 0.0997, 11.528150617530041 }, + new[] { 30.000000000000004, -0.0997, 35.091774208140095 }, + new[] { 30.000000000000004, -0.0798, 33.750904327320896 }, + new[] { 30.000000000000004, -0.0599, 32.40315158162777 }, + new[] { 30.000000000000004, -0.0400, 31.050077596965064 }, + new[] { 30.000000000000004, -0.0200, 29.69327509188113 }, + new[] { 30.000000000000004, 0.0000, 28.33435862498606 }, + new[] { 30.000000000000004, 0.0200, 26.974955046566407 }, + new[] { 30.000000000000004, 0.0400, 25.616693776603913 }, + new[] { 30.000000000000004, 0.0599, 24.261197065863925 }, + new[] { 30.000000000000004, 0.0798, 22.91007034016412 }, + new[] { 30.000000000000004, 0.0997, 21.56489279686667 }, + new[] { 40.0, -0.0997, 45.024018797189854 }, + new[] { 40.0, -0.0798, 43.68636622428101 }, + new[] { 40.0, -0.0599, 42.34185052441486 }, + new[] { 40.0, -0.0400, 40.99202962224952 }, + new[] { 40.0, -0.0200, 39.63849244500093 }, + new[] { 40.0, 0.0000, 38.282849690992855 }, + new[] { 40.0, 0.0200, 36.926724305651554 }, + new[] { 40.0, 0.0400, 35.57174178507285 }, + new[] { 40.0, 0.0599, 34.21952045137207 }, + new[] { 40.0, 0.0798, 32.87166183129923 }, + new[] { 40.0, 0.0997, 31.5297412694979 }, + new[] { 50.0, -0.0997, 54.652157586769704 }, + new[] { 50.0, -0.0798, 53.319266704395716 }, + new[] { 50.0, -0.0599, 51.97954186606304 }, + new[] { 50.0, -0.0400, 50.634535516787736 }, + new[] { 50.0, -0.0200, 49.28583097196263 }, + new[] { 50.0, 0.0000, 47.93503321632867 }, + new[] { 50.0, 0.0200, 46.583759417454765 }, + new[] { 50.0, 0.0400, 45.23362925944123 }, + new[] { 50.0, 0.0599, 43.88625525588574 }, + new[] { 50.0, 0.0798, 42.54323315977748 }, + new[] { 50.0, 0.0997, 41.20613261641401 }, + new[] { 60.00000000000001, -0.0997, 64.2503607025971 }, + new[] { 60.00000000000001, -0.0798, 62.91932863058169 }, + new[] { 60.00000000000001, -0.0599, 61.58156853535776 }, + new[] { 60.00000000000001, -0.0400, 60.23862904729555 }, + new[] { 60.00000000000001, -0.0200, 58.89369896300112 }, + new[] { 60.00000000000001, 0.0000, 57.547040626925885 }, + new[] { 60.00000000000001, 0.0200, 56.199911833784675 }, + new[] { 60.00000000000001, 0.0400, 54.85392730356455 }, + new[] { 60.00000000000001, 0.0599, 53.510694584916905 }, + new[] { 60.00000000000001, 0.0798, 52.17180450267632 }, + new[] { 60.00000000000001, 0.0997, 50.83882182989668 }, + new[] { 70.0, -0.0997, 73.78388063954164 }, + new[] { 70.0, -0.0798, 72.45700102808648 }, + new[] { 70.0, -0.0599, 71.12341092304165 }, + new[] { 70.0, -0.0400, 69.78459543842656 }, + new[] { 70.0, -0.0200, 68.44188526693415 }, + new[] { 70.0, 0.0000, 67.09719334997524 }, + new[] { 70.0, 0.0200, 65.75212749798493 }, + new[] { 70.0, 0.0400, 64.40829754257321 }, + new[] { 70.0, 0.0599, 63.06730571969745 }, + new[] { 70.0, 0.0798, 61.73073716025881 }, + new[] { 70.0, 0.0997, 60.40015062055851 }, + new[] { 80.0, -0.0997, 83.25457689135129 }, + new[] { 80.0, -0.0798, 81.93182852399568 }, + new[] { 80.0, -0.0599, 80.60238880559001 }, + new[] { 80.0, -0.0400, 79.2676325992058 }, + new[] { 80.0, -0.0200, 77.92916666616652 }, + new[] { 80.0, 0.0000, 76.58872134590663 }, + new[] { 80.0, 0.0200, 75.24790011046437 }, + new[] { 80.0, 0.0400, 73.90830846424944 }, + new[] { 80.0, 0.0599, 72.57154434889891 }, + new[] { 80.0, 0.0798, 71.23918865436896 }, + new[] { 80.0, 0.0997, 69.91277394305271 }, + }; + var entries = new List<VelocitySpeedGearshiftPreprocessor.Entry>(); + foreach (var d in data) { + entries.Add(new VelocitySpeedGearshiftPreprocessor.Entry() { + StartVelocity = d[0].KMPHtoMeterPerSecond(), + Gradient = d[1].SI<Radian>(), + EndVelocity = d[2].KMPHtoMeterPerSecond(), + }); + } + + shiftStrategy.VelocityDropData.Data = entries.ToArray(); + + } + + } + +} -- GitLab From d07e27988822d3a4d5d3ec6349040f7546c78a01 Mon Sep 17 00:00:00 2001 From: "VKMTHD\\haraldmartini" <martini@ivt.tugraz.at> Date: Mon, 17 Mar 2025 14:17:39 +0100 Subject: [PATCH 14/22] Transfer all ATShiftStrategyOptimizedTestcases --- .../ATShiftStrategyOptimizedTests.cs | 1215 ++++++++--------- 1 file changed, 546 insertions(+), 669 deletions(-) diff --git a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyOptimizedTests.cs b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyOptimizedTests.cs index 8e2fa264ae..7e05644e5c 100644 --- a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyOptimizedTests.cs +++ b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyOptimizedTests.cs @@ -26,6 +26,7 @@ using TUGraz.VectoCore.Models.SimulationComponent.Data; using TUGraz.VectoCore.Models.SimulationComponent.Data.Engine; using TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox; using TUGraz.VectoCore.Models.SimulationComponent.Impl; +using TUGraz.VectoCore.Models.SimulationComponent.Impl.Gearbox; using TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies; using TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies.ShiftPolygonCalc; using TUGraz.VectoCore.OutputData.XML.DeclarationReports.ManufacturerReport.ManufacturerReport_0_9.ManufacturerReportGroupWriter; @@ -62,43 +63,46 @@ public class ATShiftStrategyOptimizedTests out var runData, out _, out _); - - var shiftStrategy = new ATShiftStrategyOptimized(vehicleContainer.Object); + + var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx, out _); var angularVelocity = GetAngularVelocityBySpeed(vehicleSpeed, runData); var response = shiftStrategy.InitGear( 0.SI<Second>(), 1.SI<Second>(), - torque.SI<NewtonMeter>(), + torque.SI<NewtonMeter>(), angularVelocity); - + Assert.AreEqual(expectedGear, response.Gear); } + private Mock<IVehicleContainer> GetMockVehicleContainer(double speedKmh, DrivingBehavior driverBehavior, double[] gearRatios, out Mock<IVehicleDeclarationInputData> inputData, out VectoRunData runData, out GearboxData gearboxData, out Mock<ISimpleVehicleContainer> simplePt) { var vehicleContainer = new Mock<IVehicleContainer>(); - + inputData = GetMockInputData(gearRatios); runData = GetDummyVectoRunData(inputData.Object); - - vehicleContainer.Setup(c => c.RunData).Returns(runData); + //Testpowertrain var testPowertrain = GetMockTestPowertrain( - runData, + runData, out simplePt); - + vehicleContainer.Setup(c => c.SimplePowertrainBuilder.CreateTestPowertrain(It.IsAny<IVehicleContainer>(), It.IsAny<bool>())).Returns(testPowertrain.Object); - + //VehicleInfo - vehicleContainer.Setup(v => v.VehicleInfo) + vehicleContainer.Setup(c => c.VehicleInfo) .Returns(GetVehicleInfo(speedKmh.KMPHtoMeterPerSecond()).Object); + //EngineInfo + vehicleContainer.Setup(c => c.EngineInfo).Returns(GetEngineInfo(vehicleContainer, runData)); + //AxleGearInfo var axleGearInfo = new Mock<IAxlegearInfo>(); vehicleContainer.Setup(c => c.AxlegearInfo).Returns(axleGearInfo.Object); @@ -117,8 +121,7 @@ public class ATShiftStrategyOptimizedTests cycleInfo.Setup(c => c.RoadGradient).Returns(0.SI<Radian>()); - cycleInfo.Setup(c => c.CycleLookAhead(It.IsAny<Meter>())).Returns(new DrivingCycleData.DrivingCycleEntry() - { + cycleInfo.Setup(c => c.CycleLookAhead(It.IsAny<Meter>())).Returns(new DrivingCycleData.DrivingCycleEntry() { Altitude = 0.SI<Meter>() }); cycleInfo.Setup(c => c.Altitude).Returns(0.SI<Meter>()); @@ -126,8 +129,7 @@ public class ATShiftStrategyOptimizedTests //DriverINfo vehicleContainer.Setup(v => v.DriverInfo.DriverBehavior).Returns(driverBehavior); var acc = 0.SI<MeterPerSquareSecond>(); - switch (driverBehavior) - { + switch (driverBehavior) { case DrivingBehavior.Accelerating: acc = 1.SI<MeterPerSquareSecond>(); break; @@ -141,7 +143,7 @@ public class ATShiftStrategyOptimizedTests throw new ArgumentOutOfRangeException(); } - + @@ -149,17 +151,35 @@ public class ATShiftStrategyOptimizedTests gearboxData = new GearboxData(); return vehicleContainer; } + + private IEngineInfo GetEngineInfo(Mock<IVehicleContainer> vehicleContainer, VectoRunData runData) + { + //EngineInfo + var engineInfo = new Mock<IEngineInfo>(); + vehicleContainer.Setup(c => c.EngineInfo).Returns(engineInfo.Object); + engineInfo.Setup(e => e.EngineIdleSpeed).Returns(runData.EngineData.IdleSpeed); + engineInfo.Setup(e => e.EngineRatedSpeed).Returns(runData.EngineData.FullLoadCurves.First().Value.RatedSpeed); + + engineInfo.Setup(e => e.EngineSpeed).Returns(1400.RPMtoRad()); + engineInfo.Setup(e => e.EngineN95hSpeed).Returns + (runData.EngineData.FullLoadCurves.First().Value.N95hSpeed); + engineInfo.Setup(e => e.EngineN80hSpeed).Returns( + runData.EngineData.FullLoadCurves.First().Value.N80hSpeed); + engineInfo.Setup(e => e.EngineStationaryFullPower(It.IsAny<PerSecond>())).Returns((PerSecond n) => + runData.EngineData.FullLoadCurves[0].FullLoadStationaryPower(n)); + return engineInfo.Object; + } + private CycleData GetCycleData() { - return new CycleData() - { - LeftSample = new DrivingCycleData.DrivingCycleEntry() - { + return new CycleData() { + LeftSample = new DrivingCycleData.DrivingCycleEntry() { PTOActive = PTOActivity.Inactive, VehicleTargetSpeed = 10.KMPHtoMeterPerSecond() } }; } + private Mock<IVehicleInfo> GetVehicleInfo(MeterPerSecond speed) { var vehicleInfo = new Mock<IVehicleInfo>(); @@ -171,29 +191,30 @@ public class ATShiftStrategyOptimizedTests vehicleInfo.Setup(v => v.TotalMass).Returns(12000.SI<Kilogram>()); return vehicleInfo; } + private Mock<ITestPowertrain> GetMockTestPowertrain(VectoRunData runData, out Mock<ISimpleVehicleContainer> simpleContainer) { var testPt = new Mock<ITestPowertrain>(); - simpleContainer = GetSimplePowertrain(runData, + simpleContainer = GetSimplePowertrain(runData, out var testGearbox); - - - + + + testPt.Setup(t => t.Container).Returns(simpleContainer.Object); testPt.Setup(t => t.Gearbox).Returns(testGearbox.Object); - //Vehicle var vehicle = new Mock<ITestPowertrainVehicle>(); vehicle.Setup(v => v.Initialize( It.IsAny<MeterPerSecond>(), It.IsAny<Radian>())).Returns(new ResponseSuccess(this)); testPt.Setup(t => t.Vehicle).Returns(vehicle.Object); - + return testPt; } + private Mock<IVehicleDeclarationInputData> GetMockInputData(double[]? gearRatios) { var input = new Mock<IVehicleDeclarationInputData>(); @@ -204,18 +225,17 @@ public class ATShiftStrategyOptimizedTests components.Setup(c => c.GearboxInputData).Returns(gbx.Object); components.Setup(c => c.TorqueConverterInputData).Returns(tc.Object); - gearRatios = gearRatios ?? new double[] { - - }; + gearRatios = gearRatios ?? new double[] { }; var header = "Input Speed [rpm],Input Torque [Nm],Torque Loss [Nm]"; var efficiency = 0.98; var data = new List<string>(); - - foreach (var speed in new[] {0, 10000}) { - foreach (var tq in new[] {1e5, -1e5, 0}) { + + foreach (var speed in new[] { 0, 10000 }) { + foreach (var tq in new[] { 1e5, -1e5, 0 }) { data.Add(FormattableString.Invariant($"{speed:f2}, {tq:f2}, {(1 - efficiency) * Math.Abs(tq)}")); } } + var lossmap = InputDataHelper.InputDataAsTableData(header, data.ToArray()); //lossmap.Columns var gears = gearRatios.Select((x, idx) => { @@ -234,26 +254,27 @@ public class ATShiftStrategyOptimizedTests tc.Setup(t => t.TCData).Returns(tcData); return input; } + private static VectoRunData GetDummyVectoRunData(IVehicleDeclarationInputData inputData) { var nrOfGears = inputData.Components.GearboxInputData.Gears.Count; var fldData = InputDataHelper.InputDataAsTableData(EngineFldHeader, EngineFldData); var fld = FullLoadCurveReader.Create(fldData); - + // create gearbox data var tcDataAdapter = new TorqueConverterDataAdapter(); // fuel data - var fuelData = new CombustionEngineFuelData() { + var fuelData = new CombustionEngineFuelData() { ConsumptionMap = FuelConsumptionMapReader.Create( InputDataHelper.InputDataAsTableData( "engine speed [rpm] ,torque [Nm] ,fuel consumption [g/h] ,whr power electrical [W]", "500,-131,0,0", - "500,95.6,1814.959,0", - "500,573.6,9771.095,0", - "2453,-209.12,0,0", - "2453,764.8,39097.94,0" - )), + "500,95.6,1814.959,0", + "500,573.6,9771.095,0", + "2453,-209.12,0,0", + "2453,764.8,39097.94,0" + )), FuelData = DeclarationData.FuelData.Lookup(FuelType.DieselCI), }; @@ -285,65 +306,63 @@ public class ATShiftStrategyOptimizedTests GearboxType.ATSerial, GearboxType.ATPowerSplit }; - var gearboxData = gbxDataAdapter.CreateGearboxData(inputData, runData, new ATShiftStrategyOptimizedPolygonCalculator(), new GearboxType[] { - GearboxType.ATSerial, - GearboxType.ATPowerSplit - }); + var gearboxData = gbxDataAdapter.CreateGearboxData(inputData, runData, + new ATShiftStrategyOptimizedPolygonCalculator(), new GearboxType[] { + GearboxType.ATSerial, + GearboxType.ATPowerSplit + }); var gearShiftParams = gbxDataAdapter.CreateGearshiftData(1.0, runData.EngineData.IdleSpeed, GearboxType.ATSerial, nrOfGears); runData.GearboxData = gearboxData; runData.GearshiftParameters = gearShiftParams; - return runData; + return runData; } - private Mock<ISimpleVehicleContainer> GetSimplePowertrain(VectoRunData runData, out Mock<ITestPowertrainTransmission> testGearbox) + + private Mock<ISimpleVehicleContainer> GetSimplePowertrain(VectoRunData runData, + out Mock<ITestPowertrainTransmission> testGearbox) { var simplePt = new Mock<ISimpleVehicleContainer>(); testGearbox = GetMockTestGearbox(runData.GearboxData.Gears); - - + + simplePt.Setup(s => s.GearboxInfo).Returns(testGearbox.Object); - - - - - + simplePt.Setup(s => s.GearboxOutPort).Returns(testGearbox.Object); + + + + //VehiclePort return simplePt; } + private Mock<ITestPowertrainTransmission> GetMockTestGearbox(Dictionary<uint, GearData> ratios) { Mock<IAPTGearbox> amtGearbox = new Mock<IAPTGearbox>(); amtGearbox.Name = "APT_TestGearbox"; Mock<ITestPowertrainTransmission> gbx = amtGearbox.As<ITestPowertrainTransmission>(); - - + + gbx.Setup(g => g.LastUpshift).Returns(-double.MaxValue.SI<Second>()); gbx.Setup(g => g.LastDownshift).Returns(-double.MaxValue.SI<Second>()); GearshiftPosition gear = null; - gbx.SetupGet(g => g.Gear).Returns(() => { - - return gear; - }); + gbx.SetupGet(g => g.Gear).Returns(() => { return gear; }); gbx.SetupSet(g => g.SetGear = It.IsAny<GearshiftPosition>()) - .Callback<GearshiftPosition>(p => { - gear = p; - }); + .Callback<GearshiftPosition>(p => { gear = p; }); GearshiftPosition nextGear = null; gbx.SetupGet(g => g.NextGear).Returns(() => nextGear); gbx.SetupSet(g => g.SetNextGear = It.IsAny<GearshiftPosition>()) .Callback<GearshiftPosition>(p => nextGear = p); - + gbx.Setup(p => p.Initialize(It.IsAny<NewtonMeter>(), It.IsAny<PerSecond>())).Returns((NewtonMeter tq, PerSecond rpm) => { - return new ResponseSuccess(this) - { + return new ResponseSuccess(this) { Engine = { EngineSpeed = rpm, PowerRequest = tq * rpm, @@ -370,6 +389,7 @@ public class ATShiftStrategyOptimizedTests PowerRequest = n * t, EngineSpeed = n * ratio, DynamicFullLoadPower = (t / ratio + 2300.SI<NewtonMeter>()) * n * ratio, TotalTorqueDemand = t, + TorqueOutDemand = t, }, Clutch = { PowerRequest = n * t }, DeltaFullLoad = n * t / 2 * (-1) @@ -386,83 +406,6 @@ public class ATShiftStrategyOptimizedTests return gbx; } - private Mock<IAPTGearbox> GetGearbox(Dictionary<uint, GearData> ratios) - { - - Mock<IAPTGearbox> amtGearbox = new Mock<IAPTGearbox>(); - amtGearbox.Name = "APT_Gearbox"; - - var gbx = amtGearbox.As<IAPTGearbox>(); - // Mock<ITestPowertrainTransmission> gbx = amtGearbox.As<ITestPowertrainTransmission>(); - - - - - // gbx.Setup(g => g.LastUpshift).Returns(-double.MaxValue.SI<Second>()); - // gbx.Setup(g => g.LastDownshift).Returns(-double.MaxValue.SI<Second>()); - // - // GearshiftPosition gear = null; - // gbx.SetupGet(g => g.Gear).Returns(() => { - // - // return gear; - // }); - // gbx.SetupSet(g => g.SetGear = It.IsAny<GearshiftPosition>()) - // .Callback<GearshiftPosition>(p => { - // gear = p; - // }); - - - // GearshiftPosition nextGear = null; - // gbx.SetupGet(g => g.NextGear).Returns(() => nextGear); - // gbx.SetupSet(g => g.SetNextGear = It.IsAny<GearshiftPosition>()) - // .Callback<GearshiftPosition>(p => nextGear = p); - // - // gbx.Setup(p => p.Initialize(It.IsAny<NewtonMeter>(), - // It.IsAny<PerSecond>())).Returns((NewtonMeter tq, PerSecond rpm) => { - // return new ResponseSuccess(this) - // { - // Engine = { - // EngineSpeed = rpm, - // PowerRequest = tq * rpm, - // }, - // }; - // }); - // gbx.Setup(p => p.Request( - // It.IsAny<Second>(), - // It.IsAny<Second>(), - // It.IsAny<NewtonMeter>(), - // It.IsAny<PerSecond>(), - // true)).Returns(( - // Second absTime, - // Second dt, - // NewtonMeter t, - // PerSecond n, - // bool dryRun) => { - // - // var ratio = - // gbx.Object.Gear == null ? 1.0 : ratios[gbx.Object.Gear.Gear].Ratio; - // return dryRun - // ? new ResponseDryRun(this) { - // Engine = { - // PowerRequest = n * t, EngineSpeed = n * ratio, - // DynamicFullLoadPower = (t / ratio + 2300.SI<NewtonMeter>()) * n * ratio, - // TotalTorqueDemand = t, - // }, - // Clutch = { PowerRequest = n * t }, - // DeltaFullLoad = n * t / 2 * (-1) - // } - // : new ResponseSuccess(this) { - // Engine = { - // PowerRequest = n * t, - // EngineSpeed = n * ratio - // - // }, - // Clutch = { PowerRequest = n * t } - // }; - // }); - - return gbx; - } private static PerSecond GetAngularVelocityBySpeed(double speedKmh, VectoRunData runData) { // r_dyn = 0.465m, i_axle = 6.2 @@ -472,11 +415,11 @@ public class ATShiftStrategyOptimizedTests return angularVelocity; } - - - - - + + + + + public const string TcHeader = "Speed Ratio, Torque Ratio,MP1000"; public static readonly string[] TcData = new[] { @@ -517,400 +460,346 @@ public class ATShiftStrategyOptimizedTests "2100,1100,-320,0.25", }; - - - - - - - - - - - - - - - - - - - - -} + [TestCase(1, 1, 1000, 1500, 0, Description = "Engage 0-> 1C")] + public void Gearbox_Engage(int gear, int newGear, double tqNm, double nRPM, double speedKmh) + { + var gearRatios = new[] { 6.38, 4.63, 3.44, 2.59, 1.86, 1.35, 1, 0.76 }; + + var vehicleContainer = GetMockVehicleContainer(speedKmh, DrivingBehavior.Accelerating, gearRatios, + inputData: out _, + runData: out var runData, + gearboxData: out _, simplePt: out _); + + var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); + var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData: runData); + + var response = gbx.Initialize(0.SI<NewtonMeter>(), angularVelocity); + + + + var absTime = 0.SI<Second>(); + var dt = 2.SI<Second>(); + + + var expectedN = nRPM.RPMtoRad(); + angularVelocity = expectedN / gearRatios[gear]; + + + gbx.CurrentState = new ATGearboxState() + { + Gear = gbx.Gear, + }; + + var expectedT = tqNm.SI<NewtonMeter>(); + var torque = expectedT * gearRatios[gear]; + + var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, torque, angularVelocity, expectedT, expectedN, + new GearshiftPosition((uint)gear), -double.MaxValue.SI<Second>(), new ResponseSuccess(this)); + + Assert.AreEqual(newGear, shiftStrategy.NextGear.Gear); + + var shiftExpected = gear != newGear; //Different Gear + shiftExpected = shiftRequired || gbx.Disengaged; //Gearbox was disengaged + + Assert.AreEqual(shiftExpected, shiftRequired); + } + + [TestCase(2, 1, -1000, 1500, 4, DrivingBehavior.Braking, Description = "_ -> 0: disengage before halting")] + public void Gearbox_Disengange(int gear, int newGear, double tqNm, double nRPM, double speedKmh, + DrivingBehavior driverBehavior) + { + var gearRatios = new[] { 6.38, 4.63, 3.44, 2.59, 1.86, 1.35, 1, 0.76 }; + + var vehicleContainer = GetMockVehicleContainer(speedKmh, + driverBehavior, + gearRatios, + out var inputData, + out var runData, + out var gearboxData, out _); + + var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); + var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); + + gbx.Initialize(0.SI<NewtonMeter>(), angularVelocity); + + + var absTime = 0.SI<Second>(); + var dt = 2.SI<Second>(); + + + var expectedN = nRPM.RPMtoRad(); + angularVelocity = expectedN / gearRatios[gear]; + + //Called in gbx initialize + //var gearShiftPosition = shiftStrategy.InitGear(absTime, Constants.SimulationSettings.TargetTimeInterval, 1.SI<NewtonMeter>(), + // angularVelocity); + var engagedPosition = shiftStrategy.Engage(absTime, dt, null, null); + + + Assert.IsTrue(engagedPosition.Engaged); + + gbx.CurrentState = new ATGearboxState() + { + Disengaged = gbx.Disengaged, + Gear = gbx.Gear, + }; + + var expectedT = tqNm.SI<NewtonMeter>(); + var torque = expectedT * gearRatios[gear]; + + + var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, torque, angularVelocity, expectedT, expectedN, + new GearshiftPosition((uint)gear), -double.MaxValue.SI<Second>(), new ResponseSuccess(this)); + + Assert.AreEqual(newGear, shiftStrategy.NextGear.Gear); + + var shiftExpected = gear != newGear; //Different Gear + shiftExpected = shiftRequired || gbx.Disengaged; //Gearbox was disengaged + + Assert.AreEqual(shiftExpected, shiftRequired); + } + + [TestCase(2, true, 3, true, 100, 1800, 13, Description = "Upshift-TCLocked", TestName="Upshift-TCLocked")] + [TestCase(1, false, 1, true, 100, 1000, 1, Description = "Upshift-TC", TestName = "Upshift-TC")] + [TestCase(2, true, 3, true, 100, 800, 13, Description = "Upshift-TCLocked", TestName = "EarlyUpshift")] + [TestCase(1, false, 1, true, 100, 500, 1, Description = "EarlyUpshift-TC", TestName="EarlyUpshift-TC")] + public void Gearbox_Upshift(int gear, bool tcLocked, int newGear, bool newTcLocked, double tqNm, double nRPM, double speedKmh) + { + var gearRatios = new[] { 3.4, 1.9, 1.42, 1.0, 0.7, 0.62 }; + + var vehicleContainer = GetMockVehicleContainer( + speedKmh, + DrivingBehavior.Accelerating, + gearRatios, + out var inputData, out var runData, out var gearboxData, out var simplePt); + + + var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); + var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); + + var gbxResponse = gbx.Initialize(0.SI<NewtonMeter>(), angularVelocity); + + Assert.AreEqual((uint)gear, gbx.Gear.Gear); + Assert.That(gbx.Gear.TorqueConverterLocked, Is.EqualTo(tcLocked)); + + + var absTime = 0.SI<Second>(); + var dt = 2.SI<Second>(); + + gbx.CurrentState = new ATGearboxState() + { + Disengaged = gbx.Disengaged, + Gear = gbx.Gear, + }; + + + var inAngularVelocity = nRPM.RPMtoRad(); + var outAngularVelocity = inAngularVelocity / gearRatios[gear]; + + var inTorque = tqNm.SI<NewtonMeter>(); + var outTortque = inTorque * gearRatios[gear]; + + var response = new ResponseSuccess(this); + response.Engine.DynamicFullLoadTorque = 50.SI<NewtonMeter>(); + response.Engine.EngineSpeed = inAngularVelocity; + response.Engine.TorqueOutDemand = inTorque; + + + runData.GearshiftParameters.RatingFactorCurrentGear = 1.1; + + + var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, outTortque, outAngularVelocity, inTorque, inAngularVelocity, gbx.Gear, -double.MaxValue.SI<Second>(), response); + + + Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(newGear)); + Assert.That(shiftStrategy.NextGear.TorqueConverterLocked ?? true, Is.EqualTo(newTcLocked)); + + var shiftExpected = gear != newGear; //Different Gear + shiftExpected = shiftRequired || gbx.Disengaged; //Gearbox was disengaged + + Assert.AreEqual(shiftExpected, shiftRequired); + } + + [TestCase(2, true, 3, true, 100, 1800, 13, Description = "Upshift-TCLocked")] + [TestCase(1, false, 1, true, 100, 1000, 1, Description = "Upshift-TC")] + public void Gearbox_EarlyUpshift(int gear, bool tcLocked, int newGear, bool newTcLocked, double tqNm, double nRPM, double speedKmh) + { + var gearRatios = new[] { 3.4, 1.9, 1.42, 1.0, 0.7, 0.62 }; + + var vehicleContainer = GetMockVehicleContainer( + speedKmh, + DrivingBehavior.Accelerating, + gearRatios, + out var inputData, out var runData, out var gearboxData, out _); + + + var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); + var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); + + var response = gbx.Initialize(0.SI<NewtonMeter>(), angularVelocity); + + Assert.AreEqual((uint)gear, gbx.Gear.Gear); + Assert.That(gbx.Gear.TorqueConverterLocked, Is.EqualTo(tcLocked)); + + + var absTime = 0.SI<Second>(); + var dt = 2.SI<Second>(); + + gbx.CurrentState = new ATGearboxState() + { + Disengaged = gbx.Disengaged, + Gear = gbx.Gear, + }; + + + var inAngularVelocity = nRPM.RPMtoRad(); + var outAngularVelocity = inAngularVelocity / gearRatios[gear]; + + var inTorque = tqNm.SI<NewtonMeter>(); + var outTortque = inTorque * gearRatios[gear]; + + var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, outTortque, outAngularVelocity, inTorque, inAngularVelocity, gbx.Gear, -double.MaxValue.SI<Second>(), new ResponseSuccess(this)); + + + Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(newGear)); + Assert.That(shiftStrategy.NextGear.TorqueConverterLocked ?? true, Is.EqualTo(newTcLocked)); + + var shiftExpected = gear != newGear; //Different Gear + shiftExpected = shiftRequired || gbx.Disengaged; //Gearbox was disengaged + + Assert.AreEqual(shiftExpected, shiftRequired); + } -// public void TestATGearInitialize(double vehicleSpeed, double torque, int expectedGear) -// { -// var gearRatios = new[] { 3.4, 1.9, 1.42, 1.0, 0.7, 0.62 }; -// -// var gbxTypes = new[] { -// GearboxType.ATSerial -// }; -// -// var vehicleContainer = GetMockVehicleContainer( -// vehicleSpeed, -// DrivingBehavior.Accelerating, -// gearRatios, -// out var inputData, -// out var runData, -// out var gearboxData, out _); // -// var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); + [TestCase(1, false, 2, false, 100, 1000, 1, Description = "Upshift-TC")] + public void Gearbox_Upshift_TC_TC(int gear, bool tcLocked, int newGear, bool newTcLocked, double tqNm, double nRPM, double speedKmh) + { + var gearRatios = new[] { 3.4, 1.3, 1.1, 1.0, 0.7, 0.62 }; + + var vehicleContainer = GetMockVehicleContainer( + speedKmh, + DrivingBehavior.Accelerating, + gearRatios, + out var inputData, out var runData, out var gearboxData, out _); + + + var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); + var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); + + var gbxResponse = gbx.Initialize(0.SI<NewtonMeter>(), angularVelocity); + + Assert.AreEqual((uint)gear, gbx.Gear.Gear); + Assert.That(gbx.Gear.TorqueConverterLocked, Is.EqualTo(tcLocked)); + + + var absTime = 0.SI<Second>(); + var dt = 2.SI<Second>(); + + gbx.CurrentState = new ATGearboxState() + { + Disengaged = gbx.Disengaged, + Gear = gbx.Gear, + }; + + Assert.That(gbx.ModelData.GearList.First(p => p.Gear == 2).TorqueConverterLocked, Is.False, "Expected 2nd gear with TC"); + var inAngularVelocity = nRPM.RPMtoRad(); + var outAngularVelocity = inAngularVelocity / gearRatios[gear]; + + var inTorque = tqNm.SI<NewtonMeter>(); + var outTortque = inTorque * gearRatios[gear]; + + var response = new ResponseSuccess(this); + response.Engine.EngineSpeed = inAngularVelocity; + response.Engine.TorqueOutDemand = inTorque; + + + var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, outTortque, outAngularVelocity, inTorque, inAngularVelocity, gbx.Gear, -double.MaxValue.SI<Second>(), response); + + + Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(newGear)); + Assert.That(shiftStrategy.NextGear.TorqueConverterLocked ?? true, Is.EqualTo(newTcLocked)); + + var shiftExpected = gear != newGear; //Different Gear + shiftExpected = shiftRequired || gbx.Disengaged; //Gearbox was disengaged + + Assert.AreEqual(shiftExpected, shiftRequired); + } // -// var angularVelocity = GetAngularVelocityBySpeed(vehicleSpeed, runData); -// var response = gbx.Initialize(torque.SI<NewtonMeter>(), angularVelocity); // -// Assert.IsInstanceOf(typeof(ResponseSuccess), response); -// Assert.AreEqual(expectedGear, gbx.Gear.Gear); -// Assert.AreEqual(vehicleSpeed.IsEqual(0), gbx.Disengaged); -// } // // -// [TestCase(1, 1, 1000, 1500, 0, Description = "Engage 0-> 1C")] -// public void Gearbox_Engage(int gear, int newGear, double tqNm, double nRPM, double speedKmh) -// { -// var gearRatios = new[] { 6.38, 4.63, 3.44, 2.59, 1.86, 1.35, 1, 0.76 }; -// -// var vehicleContainer = GetMockVehicleContainer(speedKmh, DrivingBehavior.Accelerating, gearRatios, -// inputData: out _, -// runData: out var runData, -// gearboxData: out _, simplePt: out _); -// -// var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); -// var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData: runData); -// -// var response = gbx.Initialize(0.SI<NewtonMeter>(), angularVelocity); -// -// -// -// var absTime = 0.SI<Second>(); -// var dt = 2.SI<Second>(); -// -// -// var expectedN = nRPM.RPMtoRad(); -// angularVelocity = expectedN / gearRatios[gear]; -// -// -// gbx.CurrentState = new ATGearbox.ATGearboxState() -// { -// Gear = gbx.Gear, -// }; -// -// var expectedT = tqNm.SI<NewtonMeter>(); -// var torque = expectedT * gearRatios[gear]; -// -// var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, torque, angularVelocity, expectedT, expectedN, -// new GearshiftPosition((uint)gear), -double.MaxValue.SI<Second>(), new ResponseSuccess(this)); -// -// Assert.AreEqual(newGear, shiftStrategy.NextGear.Gear); -// -// var shiftExpected = gear != newGear; //Different Gear -// shiftExpected = shiftRequired || gbx.Disengaged; //Gearbox was disengaged -// -// Assert.AreEqual(shiftExpected, shiftRequired); -// } -// -// [TestCase(2, 1, -1000, 1500, 4, DrivingBehavior.Braking, Description = "_ -> 0: disengage before halting")] -// public void Gearbox_Disengange(int gear, int newGear, double tqNm, double nRPM, double speedKmh, -// DrivingBehavior driverBehavior) -// { -// var gearRatios = new[] { 6.38, 4.63, 3.44, 2.59, 1.86, 1.35, 1, 0.76 }; -// -// var vehicleContainer = GetMockVehicleContainer(speedKmh, -// driverBehavior, -// gearRatios, -// out var inputData, -// out var runData, -// out var gearboxData, out _); -// -// var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); -// var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); -// -// gbx.Initialize(0.SI<NewtonMeter>(), angularVelocity); -// -// -// var absTime = 0.SI<Second>(); -// var dt = 2.SI<Second>(); -// -// -// var expectedN = nRPM.RPMtoRad(); -// angularVelocity = expectedN / gearRatios[gear]; -// -// //Called in gbx initialize -// //var gearShiftPosition = shiftStrategy.InitGear(absTime, Constants.SimulationSettings.TargetTimeInterval, 1.SI<NewtonMeter>(), -// // angularVelocity); -// var engagedPosition = shiftStrategy.Engage(absTime, dt, null, null); -// -// -// Assert.IsTrue(engagedPosition.Engaged); -// -// gbx.CurrentState = new ATGearbox.ATGearboxState() -// { -// Disengaged = gbx.Disengaged, -// Gear = gbx.Gear, -// }; -// -// var expectedT = tqNm.SI<NewtonMeter>(); -// var torque = expectedT * gearRatios[gear]; -// -// -// var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, torque, angularVelocity, expectedT, expectedN, -// new GearshiftPosition((uint)gear), -double.MaxValue.SI<Second>(), new ResponseSuccess(this)); -// -// Assert.AreEqual(newGear, shiftStrategy.NextGear.Gear); -// -// var shiftExpected = gear != newGear; //Different Gear -// shiftExpected = shiftRequired || gbx.Disengaged; //Gearbox was disengaged -// -// Assert.AreEqual(shiftExpected, shiftRequired); -// } -// -// -// [TestCase(2, true, 3, true, 100, 1800, 13, Description = "Upshift-TCLocked", TestName="Upshift-TCLocked")] -// [TestCase(1, false, 1, true, 100, 1000, 1, Description = "Upshift-TC", TestName = "Upshift-TC")] -// -// -// [TestCase(2, true, 3, true, 100, 800, 13, Description = "Upshift-TCLocked", TestName = "EarlyUpshift")] -// -// [TestCase(1, false, 1, true, 100, 500, 1, Description = "EarlyUpshift-TC", TestName="EarlyUpshift-TC")] -// public void Gearbox_Upshift(int gear, bool tcLocked, int newGear, bool newTcLocked, double tqNm, double nRPM, double speedKmh) -// { -// var gearRatios = new[] { 3.4, 1.9, 1.42, 1.0, 0.7, 0.62 }; -// -// var vehicleContainer = GetMockVehicleContainer( -// speedKmh, -// DrivingBehavior.Accelerating, -// gearRatios, -// out var inputData, out var runData, out var gearboxData, out var simplePt); -// -// -// var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); -// var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); -// -// var gbxResponse = gbx.Initialize(0.SI<NewtonMeter>(), angularVelocity); -// -// Assert.AreEqual((uint)gear, gbx.Gear.Gear); -// Assert.That(gbx.Gear.TorqueConverterLocked, Is.EqualTo(tcLocked)); -// -// -// var absTime = 0.SI<Second>(); -// var dt = 2.SI<Second>(); -// -// gbx.CurrentState = new ATGearbox.ATGearboxState() -// { -// Disengaged = gbx.Disengaged, -// Gear = gbx.Gear, -// }; -// -// -// var inAngularVelocity = nRPM.RPMtoRad(); -// var outAngularVelocity = inAngularVelocity / gearRatios[gear]; -// -// var inTorque = tqNm.SI<NewtonMeter>(); -// var outTortque = inTorque * gearRatios[gear]; -// -// var response = new ResponseSuccess(this); -// response.Engine.DynamicFullLoadTorque = 50.SI<NewtonMeter>(); -// response.Engine.EngineSpeed = inAngularVelocity; -// response.Engine.TorqueOutDemand = inTorque; -// -// -// runData.GearshiftParameters.RatingFactorCurrentGear = 1.1; -// -// -// var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, outTortque, outAngularVelocity, inTorque, inAngularVelocity, gbx.Gear, -double.MaxValue.SI<Second>(), response); -// -// -// Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(newGear)); -// Assert.That(shiftStrategy.NextGear.TorqueConverterLocked ?? true, Is.EqualTo(newTcLocked)); -// -// var shiftExpected = gear != newGear; //Different Gear -// shiftExpected = shiftRequired || gbx.Disengaged; //Gearbox was disengaged -// -// Assert.AreEqual(shiftExpected, shiftRequired); -// } -// -// -// [TestCase(2, true, 3, true, 100, 1800, 13, Description = "Upshift-TCLocked")] -// [TestCase(1, false, 1, true, 100, 1000, 1, Description = "Upshift-TC")] -// public void Gearbox_EarlyUpshift(int gear, bool tcLocked, int newGear, bool newTcLocked, double tqNm, double nRPM, double speedKmh) -// { -// var gearRatios = new[] { 3.4, 1.9, 1.42, 1.0, 0.7, 0.62 }; -// -// var vehicleContainer = GetMockVehicleContainer( -// speedKmh, -// DrivingBehavior.Accelerating, -// gearRatios, -// out var inputData, out var runData, out var gearboxData, out _); -// -// -// var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); -// var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); -// -// var response = gbx.Initialize(0.SI<NewtonMeter>(), angularVelocity); -// -// Assert.AreEqual((uint)gear, gbx.Gear.Gear); -// Assert.That(gbx.Gear.TorqueConverterLocked, Is.EqualTo(tcLocked)); -// -// -// var absTime = 0.SI<Second>(); -// var dt = 2.SI<Second>(); -// -// gbx.CurrentState = new ATGearbox.ATGearboxState() -// { -// Disengaged = gbx.Disengaged, -// Gear = gbx.Gear, -// }; -// -// -// var inAngularVelocity = nRPM.RPMtoRad(); -// var outAngularVelocity = inAngularVelocity / gearRatios[gear]; -// -// var inTorque = tqNm.SI<NewtonMeter>(); -// var outTortque = inTorque * gearRatios[gear]; -// -// var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, outTortque, outAngularVelocity, inTorque, inAngularVelocity, gbx.Gear, -double.MaxValue.SI<Second>(), new ResponseSuccess(this)); -// -// -// Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(newGear)); -// Assert.That(shiftStrategy.NextGear.TorqueConverterLocked ?? true, Is.EqualTo(newTcLocked)); -// -// var shiftExpected = gear != newGear; //Different Gear -// shiftExpected = shiftRequired || gbx.Disengaged; //Gearbox was disengaged -// -// Assert.AreEqual(shiftExpected, shiftRequired); -// } -// -// -// [TestCase(1, false, 2, false, 100, 1000, 1, Description = "Upshift-TC")] -// public void Gearbox_Upshift_TC_TC(int gear, bool tcLocked, int newGear, bool newTcLocked, double tqNm, double nRPM, double speedKmh) -// { -// var gearRatios = new[] { 3.4, 1.3, 1.1, 1.0, 0.7, 0.62 }; -// -// var vehicleContainer = GetMockVehicleContainer( -// speedKmh, -// DrivingBehavior.Accelerating, -// gearRatios, -// out var inputData, out var runData, out var gearboxData, out _); -// -// -// var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); -// var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); -// -// var gbxResponse = gbx.Initialize(0.SI<NewtonMeter>(), angularVelocity); -// -// Assert.AreEqual((uint)gear, gbx.Gear.Gear); -// Assert.That(gbx.Gear.TorqueConverterLocked, Is.EqualTo(tcLocked)); -// -// -// var absTime = 0.SI<Second>(); -// var dt = 2.SI<Second>(); -// -// gbx.CurrentState = new ATGearbox.ATGearboxState() -// { -// Disengaged = gbx.Disengaged, -// Gear = gbx.Gear, -// }; -// -// Assert.That(gbx.ModelData.GearList.First(p => p.Gear == 2).TorqueConverterLocked, Is.False, "Expected 2nd gear with TC"); -// var inAngularVelocity = nRPM.RPMtoRad(); -// var outAngularVelocity = inAngularVelocity / gearRatios[gear]; -// -// var inTorque = tqNm.SI<NewtonMeter>(); -// var outTortque = inTorque * gearRatios[gear]; -// -// var response = new ResponseSuccess(this); -// response.Engine.EngineSpeed = inAngularVelocity; -// response.Engine.TorqueOutDemand = inTorque; -// -// -// var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, outTortque, outAngularVelocity, inTorque, inAngularVelocity, gbx.Gear, -double.MaxValue.SI<Second>(), response); -// -// -// Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(newGear)); -// Assert.That(shiftStrategy.NextGear.TorqueConverterLocked ?? true, Is.EqualTo(newTcLocked)); -// -// var shiftExpected = gear != newGear; //Different Gear -// shiftExpected = shiftRequired || gbx.Disengaged; //Gearbox was disengaged -// -// Assert.AreEqual(shiftExpected, shiftRequired); -// } -// -// -// -// -// [TestCase(3, true, 2, true, 900, 600, 15, Description = "Downshift", TestName="Gearbox_DownShift_1")] -// public void Gearbox_Downshift(int gear, bool tcLocked, int newGear, bool newTcLocked, double tqNm, double nRPM, double speedKmh) -// { -// var gearRatios = new[] { 3.4, 1.9, 1.42, 1.0, 0.7, 0.62 }; -// -// var vehicleContainer = GetMockVehicleContainer( -// speedKmh, -// DrivingBehavior.Accelerating, -// gearRatios, -// out var inputData, out var runData, out var gearboxData, out var simplePt); -// -// vehicleContainer.Setup(v => v.DriverInfo.DrivingAction).Returns(DrivingAction.Accelerate); -// -// var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); -// var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); -// -// var gbxResponse = gbx.Initialize(0.SI<NewtonMeter>(), angularVelocity); -// -// Assert.AreEqual((uint)gear, gbx.Gear.Gear); -// Assert.That(gbx.Gear.TorqueConverterLocked, Is.EqualTo(tcLocked)); -// -// -// var absTime = 0.SI<Second>(); -// var dt = 2.SI<Second>(); -// -// gbx.CurrentState = new ATGearbox.ATGearboxState() -// { -// Disengaged = gbx.Disengaged, -// Gear = gbx.Gear, -// }; -// -// -// var inAngularVelocity = nRPM.RPMtoRad(); -// var outAngularVelocity = inAngularVelocity / gearRatios[gear]; -// -// var inTorque = tqNm.SI<NewtonMeter>(); -// var outTortque = inTorque * gearRatios[gear]; -// -// var response = new ResponseSuccess(this); -// response.Engine.EngineSpeed = inAngularVelocity; -// response.Engine.TorqueOutDemand = inTorque; -// -// -// var mockPort = new Mock<ITnOutPort>(); -// -// simplePt.Setup(s => s.GearboxOutPort).Returns(mockPort.Object); -// mockPort.Setup(p => p.Request( -// It.IsAny<Second>(), -// It.IsAny<Second>(), -// It.IsAny<NewtonMeter>(), -// It.IsAny<PerSecond>(), -// true -// )).Returns((Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, bool dryRun) => { -// var response = new ResponseDryRun(this); -// response.Engine.PowerRequest = outTorque * outAngularVelocity; -// return response; -// }); -// -// -// -// -// var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, outTortque, outAngularVelocity, inTorque, inAngularVelocity, gbx.Gear, -double.MaxValue.SI<Second>(), response); -// -// -// Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(newGear)); -// Assert.That(shiftStrategy.NextGear.TorqueConverterLocked ?? true, Is.EqualTo(newTcLocked)); -// -// var shiftExpected = gear != newGear; //Different Gear -// shiftExpected = shiftRequired || gbx.Disengaged; //Gearbox was disengaged -// -// Assert.AreEqual(shiftExpected, shiftRequired); -// } + [TestCase(3, true, 2, true, 900, 600, 15, Description = "Downshift", TestName="Gearbox_DownShift_1")] + public void Gearbox_Downshift(int gear, bool tcLocked, int newGear, bool newTcLocked, double tqNm, double nRPM, double speedKmh) + { + var gearRatios = new[] { 3.4, 1.9, 1.42, 1.0, 0.7, 0.62 }; + + var vehicleContainer = GetMockVehicleContainer( + speedKmh, + DrivingBehavior.Accelerating, + gearRatios, + out var inputData, out var runData, out var gearboxData, out var simplePt); + + vehicleContainer.Setup(v => v.DriverInfo.DrivingAction).Returns(DrivingAction.Accelerate); + + var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); + var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); + + var gbxResponse = gbx.Initialize(0.SI<NewtonMeter>(), angularVelocity); + + Assert.AreEqual((uint)gear, gbx.Gear.Gear); + Assert.That(gbx.Gear.TorqueConverterLocked, Is.EqualTo(tcLocked)); + + + var absTime = 0.SI<Second>(); + var dt = 2.SI<Second>(); + + gbx.CurrentState = new ATGearboxState() + { + Disengaged = gbx.Disengaged, + Gear = gbx.Gear, + }; + + + var inAngularVelocity = nRPM.RPMtoRad(); + var outAngularVelocity = inAngularVelocity / gearRatios[gear]; + + var inTorque = tqNm.SI<NewtonMeter>(); + var outTortque = inTorque * gearRatios[gear]; + + var response = new ResponseSuccess(this); + response.Engine.EngineSpeed = inAngularVelocity; + response.Engine.TorqueOutDemand = inTorque; + + + var mockPort = new Mock<ITnOutPort>(); + + simplePt.Setup(s => s.GearboxOutPort).Returns(mockPort.Object); + mockPort.Setup(p => p.Request( + It.IsAny<Second>(), + It.IsAny<Second>(), + It.IsAny<NewtonMeter>(), + It.IsAny<PerSecond>(), + true + )).Returns((Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, bool dryRun) => { + var response = new ResponseDryRun(this); + response.Engine.PowerRequest = outTorque * outAngularVelocity; + return response; + }); + + + + + var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, outTortque, outAngularVelocity, inTorque, inAngularVelocity, gbx.Gear, -double.MaxValue.SI<Second>(), response); + + + Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(newGear)); + Assert.That(shiftStrategy.NextGear.TorqueConverterLocked ?? true, Is.EqualTo(newTcLocked)); + + var shiftExpected = gear != newGear; //Different Gear + shiftExpected = shiftRequired || gbx.Disengaged; //Gearbox was disengaged + + Assert.AreEqual(shiftExpected, shiftRequired); + } // // [TestCase(3, true, 2, true, 200, 700, 15, Description = "Downshift_3", TestName = "Gearbox_DownShift_3")] // public void Gearbox_Downshift_2(int gear, bool tcLocked, int newGear, bool newTcLocked, double tqNm, double nRPM, @@ -991,133 +880,129 @@ public class ATShiftStrategyOptimizedTests // Assert.AreEqual(shiftExpected, shiftRequired); // } // -// [TestCase(3, true, 2, true, 1700, 700, 15, Description = "Downshift", TestName = "Gearbox_Early_DownShift_1")] -// public void Gearbox_Early_Downshift(int gear, bool tcLocked, int newGear, bool newTcLocked, double tqNm, double nRPM, double speedKmh) -// { -// var gearRatios = new[] { 3.4, 1.9, 1.42, 1.0, 0.7, 0.62 }; -// -// var vehicleContainer = GetMockVehicleContainer( -// speedKmh, -// DrivingBehavior.Accelerating, -// gearRatios, -// out var inputData, out var runData, out var gearboxData, out var simplePt); -// -// vehicleContainer.Setup(v => v.DriverInfo.DrivingAction).Returns(DrivingAction.Accelerate); -// -// var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); -// var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); -// -// var gbxResponse = gbx.Initialize(0.SI<NewtonMeter>(), angularVelocity); -// -// Assert.AreEqual((uint)gear, gbx.Gear.Gear); -// Assert.That(gbx.Gear.TorqueConverterLocked, Is.EqualTo(tcLocked)); -// -// -// var absTime = 0.SI<Second>(); -// var dt = 2.SI<Second>(); -// -// gbx.CurrentState = new ATGearbox.ATGearboxState() -// { -// Disengaged = gbx.Disengaged, -// Gear = gbx.Gear, -// }; -// -// -// var inAngularVelocity = nRPM.RPMtoRad(); -// var outAngularVelocity = inAngularVelocity / gearRatios[gear]; -// -// var inTorque = tqNm.SI<NewtonMeter>(); -// var outTortque = inTorque * gearRatios[gear]; -// -// var response = new ResponseSuccess(this); -// response.Engine.EngineSpeed = inAngularVelocity; -// response.Engine.TorqueOutDemand = inTorque; -// -// -// var mockPort = new Mock<ITnOutPort>(); -// -// simplePt.Setup(s => s.GearboxOutPort).Returns(mockPort.Object); -// mockPort.Setup(p => p.Request( -// It.IsAny<Second>(), -// It.IsAny<Second>(), -// It.IsAny<NewtonMeter>(), -// It.IsAny<PerSecond>(), -// true -// )).Returns((Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, bool dryRun) => { -// var response = new ResponseDryRun(this); -// response.Engine.PowerRequest = outTorque * outAngularVelocity; -// return response; -// }); -// -// -// -// -// var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, outTortque, outAngularVelocity, inTorque, inAngularVelocity, gbx.Gear, -double.MaxValue.SI<Second>(), response); -// -// -// Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(newGear)); -// Assert.That(shiftStrategy.NextGear.TorqueConverterLocked ?? true, Is.EqualTo(newTcLocked)); -// -// var shiftExpected = gear != newGear; //Different Gear -// shiftExpected = shiftRequired || gbx.Disengaged; //Gearbox was disengaged -// -// Assert.AreEqual(shiftExpected, shiftRequired); -// } -// -// private ATShiftStrategy GetShiftStrategyAndGearbox(Mock<IVehicleContainer> vehicleContainer, out ATGearbox gbx) -// { -// return GetShiftStrategyAndGearbox(vehicleContainer, out gbx, out _); -// } -// -// private ATShiftStrategy GetShiftStrategyAndGearbox(Mock<IVehicleContainer> vehicleContainer, out ATGearbox gbx, -// out Mock<ITnOutPort> gbxNextComponent) -// { -// var shiftStrategy = new ATShiftStrategyOptimized(vehicleContainer.Object); -// -// gbx = new ATGearbox(vehicleContainer.Object, shiftStrategy); -// var mockPort = new Mock<ITnOutPort>(); -// NewtonMeter tqRequest = null; -// PerSecond rpmRequest = null; -// mockPort.Setup(p => p.Initialize(It.IsAny<NewtonMeter>(), -// It.IsAny<PerSecond>())).Returns((NewtonMeter tq, PerSecond rpm) => { -// tqRequest = tq; -// rpmRequest = rpm; -// return new ResponseSuccess(this) -// { -// Engine = { -// EngineSpeed = rpm, -// PowerRequest = tq * rpm, -// }, -// }; -// }); -// mockPort.Setup(p => p.Request(It.IsAny<Second>(), It.IsAny<Second>(), It.IsAny<NewtonMeter>(), -// It.IsAny<PerSecond>(), true)).Returns(new ResponseDryRun(this)); -// -// var idleController = new Mock<IIdleController>(); -// -// -// gbx.IdleController = idleController.Object; -// gbx.Connect(mockPort.Object); -// -// gbxNextComponent = mockPort; -// return shiftStrategy; -// } -// -// /// <summary> -// /// Calculated the angular velocity based on the vehicle speed -// /// </summary> -// /// <param name="speedKmh"></param> -// /// <param name="runData"></param> -// /// <returns></returns> -// private static PerSecond GetAngularVelocityBySpeed(double speedKmh, VectoRunData runData) -// { -// // r_dyn = 0.465m, i_axle = 6.2 -// var angularVelocity = -// speedKmh.KMPHtoMeterPerSecond() -// / runData.VehicleData.DynamicTyreRadius * 6.2; -// return angularVelocity; -// } -// + [TestCase(3, true, 2, true, 1700, 700, 15, Description = "Downshift", TestName = "Gearbox_Early_DownShift_1")] + public void Gearbox_Early_Downshift(int gear, bool tcLocked, int newGear, bool newTcLocked, double tqNm, double nRPM, double speedKmh) + { + var gearRatios = new[] { 3.4, 1.9, 1.42, 1.0, 0.7, 0.62 }; + + var vehicleContainer = GetMockVehicleContainer( + speedKmh, + DrivingBehavior.Accelerating, + gearRatios, + out var inputData, out var runData, out var gearboxData, out var simplePt); + + vehicleContainer.Setup(v => v.DriverInfo.DrivingAction).Returns(DrivingAction.Accelerate); + + var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); + var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); + + var gbxResponse = gbx.Initialize(0.SI<NewtonMeter>(), angularVelocity); + + Assert.AreEqual((uint)gear, gbx.Gear.Gear); + Assert.That(gbx.Gear.TorqueConverterLocked, Is.EqualTo(tcLocked)); + + + var absTime = 0.SI<Second>(); + var dt = 2.SI<Second>(); + + gbx.CurrentState = new ATGearboxState() + { + Disengaged = gbx.Disengaged, + Gear = gbx.Gear, + }; + + + var inAngularVelocity = nRPM.RPMtoRad(); + var outAngularVelocity = inAngularVelocity / gearRatios[gear]; + + var inTorque = tqNm.SI<NewtonMeter>(); + var outTortque = inTorque * gearRatios[gear]; + + var response = new ResponseSuccess(this); + response.Engine.EngineSpeed = inAngularVelocity; + response.Engine.TorqueOutDemand = inTorque; + + + var mockPort = new Mock<ITnOutPort>(); + + simplePt.Setup(s => s.GearboxOutPort).Returns(mockPort.Object); + mockPort.Setup(p => p.Request( + It.IsAny<Second>(), + It.IsAny<Second>(), + It.IsAny<NewtonMeter>(), + It.IsAny<PerSecond>(), + true + )).Returns((Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, bool dryRun) => { + var response = new ResponseDryRun(this); + response.Engine.PowerRequest = outTorque * outAngularVelocity; + return response; + }); + + + + + var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, outTortque, outAngularVelocity, inTorque, inAngularVelocity, gbx.Gear, -double.MaxValue.SI<Second>(), response); + + + Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(newGear)); + Assert.That(shiftStrategy.NextGear.TorqueConverterLocked ?? true, Is.EqualTo(newTcLocked)); + + var shiftExpected = gear != newGear; //Different Gear + shiftExpected = shiftRequired || gbx.Disengaged; //Gearbox was disengaged + + Assert.AreEqual(shiftExpected, shiftRequired); + } + + + private ATShiftStrategyOptimized GetShiftStrategyAndGearbox(Mock<IVehicleContainer> vehicleContainer, + out APTGearbox gbx) + { + return GetShiftStrategyAndGearbox(vehicleContainer, out gbx, out _); + } + + private ATShiftStrategyOptimized GetShiftStrategyAndGearbox(Mock<IVehicleContainer> vehicleContainer, + out APTGearbox gbx, + out Mock<ITnOutPort> gbxNextComponent) + { + var shiftStrategy = new ATShiftStrategyOptimized(vehicleContainer.Object); + + var gbxMock = new Mock<APTGearbox>(vehicleContainer.Object, shiftStrategy) { + CallBase = true + }; + + gbx = gbxMock.Object; + shiftStrategy.Gearbox = gbx; + + var mockPort = new Mock<ITnOutPort>(); + NewtonMeter tqRequest = null; + PerSecond rpmRequest = null; + + mockPort.Setup(p => p.Initialize(It.IsAny<NewtonMeter>(), + It.IsAny<PerSecond>())).Returns((NewtonMeter tq, PerSecond rpm) => { + tqRequest = tq; + rpmRequest = rpm; + return new ResponseSuccess(this) { + Engine = { + EngineSpeed = rpm, + PowerRequest = tq * rpm, + }, + }; + }); + + mockPort.Setup(p => p.Request(It.IsAny<Second>(), It.IsAny<Second>(), It.IsAny<NewtonMeter>(), + It.IsAny<PerSecond>(), true)).Returns(new ResponseDryRun(this)); + + var idleController = new Mock<IIdleController>(); + + + gbx.IdleController = idleController.Object; + gbx.Connect(mockPort.Object); + + gbxNextComponent = mockPort; + return shiftStrategy; + } +} + // private Mock<IVehicleContainer> GetMockVehicleContainer(double speedKmh, DrivingBehavior driverBehavior, // double[] gearRatios, // out IVehicleDeclarationInputData inputData, out VectoRunData runData, out GearboxData gearboxData, @@ -1292,14 +1177,6 @@ public class ATShiftStrategyOptimizedTests // // // -// [TestCase(2, 3, 400, 2300, 5, DrivingBehavior.Accelerating, Description = "Upshift")] -// public void Gearbox_EmergencyShift(int gear, int newGear, double tqNm, double nRPM, double speedKmh, -// DrivingBehavior driverBehavior) -// { -// -// } -// -// // private static VectoRunData GetDummyVectoRunData(IVehicleDeclarationInputData inputData) // { // var nrOfGears = inputData.Components.GearboxInputData.Gears.Count; -- GitLab From 19abb7dc4996ea97b5848a757cc54a07797afc1b Mon Sep 17 00:00:00 2001 From: "VKMTHD\\haraldmartini" <martini@ivt.tugraz.at> Date: Mon, 17 Mar 2025 14:21:27 +0100 Subject: [PATCH 15/22] Remove ATShiftStrategyTests (all tests covered in ATShiftStrategyOptimizedTests) --- .../GearShiftStrategy/ATShiftStrategyTests.cs | 240 ------------------ 1 file changed, 240 deletions(-) delete mode 100644 Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyTests.cs diff --git a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyTests.cs b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyTests.cs deleted file mode 100644 index 0e1b66fe18..0000000000 --- a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyTests.cs +++ /dev/null @@ -1,240 +0,0 @@ -using Moq; -using NUnit.Framework; -using NUnit.Framework.Interfaces; -using TUGraz.VectoCommon.InputData; -using TUGraz.VectoCommon.Models; -using TUGraz.VectoCommon.Utils; -using TUGraz.VectoCore.InputData.Reader.ComponentData; -using TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.SimulationComponents; -using TUGraz.VectoCore.Models.Connector.Ports; -using TUGraz.VectoCore.Models.Connector.Ports.Impl; -using TUGraz.VectoCore.Models.Declaration; -using TUGraz.VectoCore.Models.Simulation; -using TUGraz.VectoCore.Models.Simulation.Data; -using TUGraz.VectoCore.Models.Simulation.DataBus; -using TUGraz.VectoCore.Models.SimulationComponent; -using TUGraz.VectoCore.Models.SimulationComponent.Data; -using TUGraz.VectoCore.Models.SimulationComponent.Data.Engine; -using TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox; -using TUGraz.VectoCore.Models.SimulationComponent.Impl; -using TUGraz.VectoCore.Models.SimulationComponent.Impl.Gearbox; -using TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies; -using TUGraz.VectoCore.Tests.Utils; -using Assert = NUnit.Framework.Assert; - -namespace TUGraz.Vecto.UnitTests.TestCases.Components.GearShiftStrategy; - -public class ATShiftStrategyTests -{ - [Test, - TestCase(0, 100, 1), - TestCase(0, 200, 1), - TestCase(5, 100, 1), - TestCase(5, 300, 1), - TestCase(5, 600, 1), - TestCase(15, 100, 3), - TestCase(15, 300, 3), - TestCase(15, 600, 3), - TestCase(40, 100, 6), - TestCase(40, 300, 6), - TestCase(40, 600, 6), - TestCase(70, 100, 6), - TestCase(70, 300, 6), - TestCase(70, 600, 6), - ] - public void TestATGearInitialize(double vehicleSpeed, double torque, int expectedGear) - { - var inputData = GetMockInputData(); - var gbxTypes = new[] { - GearboxType.ATSerial - }; - var runData = GetDummyVectoRunData(inputData.Components.GearboxInputData.Gears.Count); - var shiftPolygonCalc = GetMockShiftPolygonCalc(); - - // create gearbox data - var tcDataAdapter = new TorqueConverterDataAdapter(); - var gearboxData = new GearboxDataAdapter(tcDataAdapter).CreateGearboxData(inputData, runData, shiftPolygonCalc, gbxTypes); - runData.GearboxData = gearboxData; - - var vehicleContainer = GetMockVehicleContainer(runData, out var vehicleInfo); - vehicleInfo.Setup(v => v.VehicleSpeed).Returns(vehicleSpeed.KMPHtoMeterPerSecond()); - var shiftStrategy = new ATShiftStrategyOptimized(vehicleContainer); - - var gearbox = new APTGearbox(vehicleContainer, shiftStrategy); - - var mockPort = new Mock<ITnOutPort>(); - NewtonMeter tqRequest = null; - PerSecond rpmRequest = null; - mockPort.Setup(p => p.Initialize(It.IsAny<NewtonMeter>(), - It.IsAny<PerSecond>())).Returns((NewtonMeter tq, PerSecond rpm) => { - tqRequest = tq; - rpmRequest = rpm; - return new ResponseSuccess(this) { - Engine = { - EngineSpeed = rpm, - PowerRequest = tq * rpm, - } - }; - }); - gearbox.Connect(mockPort.Object); - - // r_dyn = 0.465m, i_axle = 6.2 - var angularVelocity = vehicleSpeed.KMPHtoMeterPerSecond() / runData.VehicleData.DynamicTyreRadius * 6.2; - - var response = gearbox.Initialize(torque.SI<NewtonMeter>(), angularVelocity); - - Assert.IsInstanceOf(typeof(ResponseSuccess), response); - Assert.AreEqual(expectedGear, gearbox.Gear.Gear); - Assert.AreEqual(vehicleSpeed.IsEqual(0), gearbox.Disengaged); - } - - private static VectoRunData GetDummyVectoRunData(int inputData) - { - var fldData = InputDataHelper.InputDataAsTableData(EngineFldHeader, EngineFldData); - var fld = FullLoadCurveReader.Create(fldData); - var engineIdlingSpeed = 600.RPMtoRad(); - var runData = new VectoRunData() { - Cycle = new DrivingCycleData() { - CycleType = CycleType.DistanceBased, - }, - VehicleData = new VehicleData() { - DynamicTyreRadius = 0.465.SI<Meter>(), - }, - EngineData = new CombustionEngineData() { - Inertia = 0.SI<KilogramSquareMeter>(), - FullLoadCurves = new Dictionary<uint, EngineFullLoadCurve>() - }, - GearshiftParameters = new ShiftStrategyParameters() { - LoadStageThresoldsUp = DeclarationData.GearboxTCU.LoadStageThresholdsUp, - LoadStageThresoldsDown = DeclarationData.GearboxTCU.LoadStageThresoldsDown, - ShiftSpeedsTCToLocked = engineIdlingSpeed == null ? null : DeclarationData.GearboxTCU.ShiftSpeedsTCToLocked - .Select(x => x.Select(y => y + engineIdlingSpeed.AsRPM).ToArray()).ToArray(), - } - }; - for(uint i = 0; i <= inputData; i++) - runData.EngineData.FullLoadCurves[i] = fld; - return runData; - } - - private static IShiftPolygonCalculator GetMockShiftPolygonCalc() - { - var shiftPolygonCalc = new Mock<IShiftPolygonCalculator>(); - var downshift = new List<ShiftPolygon.ShiftPolygonEntry>() { }; - var upshift = new List<ShiftPolygon.ShiftPolygonEntry>() { }; - var shiftpolygon = new ShiftPolygon(downshift, upshift); - shiftPolygonCalc.Setup(s => s.ComputeDeclarationShiftPolygon(It.IsIn(GearboxType.ATSerial), It.IsAny<int>(), - It.IsAny<EngineFullLoadCurve>(), It.IsAny<IList<ITransmissionInputData>>(), - It.IsAny<CombustionEngineData>(), It.IsAny<double>(), It.IsAny<Meter>(), It.IsAny<ElectricMotorData>())) - .Returns(shiftpolygon); - return shiftPolygonCalc.Object; - } - - private static IVehicleContainer GetMockVehicleContainer(VectoRunData runData, out Mock<IVehicleInfo> vehicleInfo) - { - var vehicleContainer = new Mock<IVehicleContainer>(); - vehicleInfo = new Mock<IVehicleInfo>(); - var engineInfo = new Mock<IEngineInfo>(); - var ptBuilder = new Mock<ISimplePowertrainBuilder>(); - var testPt = new Mock<ITestPowertrain>(); - var testContainer = new Mock<ISimpleVehicleContainer>(); - var vehiclePort = new Mock<ITestPowertrainVehicle>(); - var testGbx = new Mock<ITestPowertrainTransmission>(); - - vehicleContainer.Setup(c => c.RunData).Returns(runData); - vehicleContainer.Setup(c => c.VehicleInfo).Returns(vehicleInfo.Object); - vehicleContainer.Setup(c => c.EngineInfo).Returns(engineInfo.Object); - vehicleContainer.Setup(c => c.SimplePowertrainBuilder).Returns(ptBuilder.Object); - - engineInfo.Setup(e => e.EngineIdleSpeed).Returns(600.RPMtoRad()); - engineInfo.Setup(e => e.EngineRatedSpeed).Returns(2000.RPMtoRad()); - - ptBuilder.Setup(b => b.CreateTestPowertrain(It.IsAny<IVehicleContainer>(), It.IsAny<bool>())).Returns(testPt.Object); - - testPt.Setup(t => t.Gearbox).Returns(testGbx.Object); - testPt.Setup(t => t.Container).Returns(testContainer.Object); - testPt.Setup(t => t.Vehicle).Returns(vehiclePort.Object); - - testContainer.Setup(c => c.RunData).Returns(runData); - testContainer.Setup(c => c.GearboxCtl).Returns(new APTGearbox(testContainer.Object, null)); - - return vehicleContainer.Object; - } - - private IVehicleDeclarationInputData GetMockInputData() - { - var input = new Mock<IVehicleDeclarationInputData>(); - var components = new Mock<IVehicleComponentsDeclaration>(); - input.Setup(i => i.Components).Returns(components.Object); - var gbx = new Mock<IGearboxDeclarationInputData>(); - var tc = new Mock<ITorqueConverterDeclarationInputData>(); - - components.Setup(c => c.GearboxInputData).Returns(gbx.Object); - components.Setup(c => c.TorqueConverterInputData).Returns(tc.Object); - var gearRatios = new double[] { - 3.4, 1.9, 1.42, 1.0, 0.7, 0.62 - }; - var header = "Input Speed [rpm],Input Torque [Nm],Torque Loss [Nm]"; - var efficiency = 0.98; - var data = new List<string>(); - foreach (var speed in new[] {0, 10000}) { - foreach (var tq in new[] {1e5, -1e5, 0}) { - data.Add($"{speed:f2}, {tq:f2}, {(1 - efficiency) * Math.Abs(tq)}"); - } - } - var lossmap = InputDataHelper.InputDataAsTableData(header, data.ToArray()); - var gears = gearRatios.Select((x, idx) => { - var gear = new Mock<ITransmissionInputData>(); - gear.Setup(g => g.Ratio).Returns(x); - gear.Setup(g => g.Gear).Returns(idx + 1); - //gear.Setup(g => g.Efficiency).Returns(0.98); - gear.Setup(g => g.LossMap).Returns(lossmap); - return gear.Object; - }).ToList(); - gbx.Setup(g => g.Type).Returns(GearboxType.ATSerial); - gbx.Setup(g => g.Gears).Returns(gears); - - var tcData = InputDataHelper.InputDataAsTableData(TcHeader, TcData); - tc.Setup(t => t.TCData).Returns(tcData); - return input.Object; - } - - public const string TcHeader = "Speed Ratio, Torque Ratio,MP1000"; - - public static readonly string[] TcData = new[] { - "0.0,1.80,377.80", - "0.1,1.71,365.21", - "0.2,1.61,352.62", - "0.3,1.52,340.02", - "0.4,1.42,327.43", - "0.5,1.33,314.84", - "0.6,1.23,302.24", - "0.7,1.14,264.46", - "0.8,1.04,226.68", - "0.9,1.02,188.90", - "1.0,1.0,0.00", - "1.100,0.999,-40.34", - "1.222,0.998,-80.34", - "1.375,0.997,-136.11", - "1.571,0.996,-216.52", - "1.833,0.995,-335.19", - "2.200,0.994,-528.77", - "2.750,0.993,-883.40", - "4.400,0.992,-2462.17", - "11.000,0.991,-16540.98", - }; - - public const string EngineFldHeader = "engine speed [1/min],full load torque [Nm],motoring torque [Nm],PT1 [s]"; - - public static readonly string[] EngineFldData = new[] { - "560,1180,-149,0.6", - "600,1282,-148,0.6", - "799.9999999,1791,-149,0.6", - "1000,2300,-160,0.6", - "1200,2300,-179,0.6", - "1400,2300,-203,0.6", - "1599.999999,2079,-235,0.49", - "1800,1857,-264,0.25", - "2000.000001,1352,-301,0.25", - "2100,1100,-320,0.25", - }; -} \ No newline at end of file -- GitLab From 4b3faa2048bc0e6b1ec82ffd68e7afc498a70609 Mon Sep 17 00:00:00 2001 From: "VKMTHD\\haraldmartini" <martini@ivt.tugraz.at> Date: Mon, 17 Mar 2025 14:38:50 +0100 Subject: [PATCH 16/22] Fixed requestdryrun with gear method in MTShiftStrategy --- .../Impl/Shiftstrategies/MTShiftStrategy.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Shiftstrategies/MTShiftStrategy.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Shiftstrategies/MTShiftStrategy.cs index 78aafdcb9c..90c57a49da 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Shiftstrategies/MTShiftStrategy.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Shiftstrategies/MTShiftStrategy.cs @@ -230,11 +230,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies TestPowertrain.UpdateComponents(); var testGearbox = TestPowertrain.Gearbox; var tmpGear = testGearbox.Gear; - // _gearbox.Gear = currentGear; + + testGearbox.SetGear = currentGear; - // _gearbox.Gear = tmpGear; - testGearbox.SetGear = tmpGear; + var response = (ResponseDryRun)testGearbox.Request(absTime, dt, outTorque, outAngularVelocity, true); + + testGearbox.SetGear = tmpGear; return response; } -- GitLab From 789e2c6c41894358cc319196f5f69f46b383853a Mon Sep 17 00:00:00 2001 From: "VKMTHD\\haraldmartini" <martini@ivt.tugraz.at> Date: Mon, 17 Mar 2025 14:48:37 +0100 Subject: [PATCH 17/22] Mock overloaded version of create test powertrain --- .../PowertrainBuilderComponentTests.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Testing/IntegrationTests/VECTO IntegrationTests/TestCases/Declaration/PowertrainBuilderTests/PowertrainBuilderComponentTests.cs b/Testing/IntegrationTests/VECTO IntegrationTests/TestCases/Declaration/PowertrainBuilderTests/PowertrainBuilderComponentTests.cs index 52c49f0b49..1e7118d16b 100644 --- a/Testing/IntegrationTests/VECTO IntegrationTests/TestCases/Declaration/PowertrainBuilderTests/PowertrainBuilderComponentTests.cs +++ b/Testing/IntegrationTests/VECTO IntegrationTests/TestCases/Declaration/PowertrainBuilderTests/PowertrainBuilderComponentTests.cs @@ -105,9 +105,12 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation var retVal = new Mock<ISimplePowertrainBuilder>(); //var ptBuilder = new SimplePowertrainBuilder(_kernel.Get<IPowertrainComponentFactory>(), _kernel.Get<IShiftStrategyFactory>()); retVal.Setup(b => b.CreateTestPowertrain(It.IsAny<IVehicleContainer>(), It.IsAny<bool>(), - It.IsAny<VectoSimulationJobType?>())) - .Returns((IVehicleContainer container, bool createDriver, VectoSimulationJobType? jobType) => + It.IsAny<VectoSimulationJobType>())) + .Returns((IVehicleContainer container, bool createDriver, VectoSimulationJobType jobType) => _simplePowertrainBuilder.CreateTestPowertrain(container, createDriver, jobType)); + retVal.Setup(b => b.CreateTestPowertrain(It.IsAny<IVehicleContainer>(), It.IsAny<bool>())) + .Returns((IVehicleContainer container, bool createDriver) => + _simplePowertrainBuilder.CreateTestPowertrain(container, createDriver)); return retVal.Object; } -- GitLab From 056fb0b1b3bd272a386b02e8ffe574b0e821af18 Mon Sep 17 00:00:00 2001 From: "VKMTHD\\haraldmartini" <martini@ivt.tugraz.at> Date: Tue, 18 Mar 2025 11:33:46 +0100 Subject: [PATCH 18/22] Added PEVAMTShiftStrategyTests.cs Use Gearbox instead of EM in PEVAMTShiftStrategy.cs Updated PEV Shiftpolygon calculation --- .../PEVAMTShiftStrategyTests.cs | 140 +++-- .../GearShiftStrategy/PEV_ShiftLineTests.cs | 587 +++++++++++++++++- .../GearBoxDataAdapter.cs | 11 +- .../Models/Declaration/DeclarationData.cs | 109 +++- .../Simulation/DataBus/IElectricMotorInfo.cs | 3 +- .../PowertrainComponentNinjectModule.cs | 2 +- .../ElectricMotor/ElectricMotorData.cs | 30 + .../Data/Gearbox/ShiftPolygon.cs | 6 +- .../Data/Gearbox/TransmissionLossMap.cs | 54 +- .../SimulationComponent/ITestPowertrain.cs | 4 +- .../SimulationComponent/Impl/ElectricMotor.cs | 17 +- .../Shiftstrategies/PEVAMTShiftStrategy.cs | 142 +++-- .../PEVAMTShiftStrategyPolygonCreator.cs | 58 +- .../SimulationComponent/Impl/Vehicle.cs | 4 +- 14 files changed, 987 insertions(+), 180 deletions(-) diff --git a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/PEVAMTShiftStrategyTests.cs b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/PEVAMTShiftStrategyTests.cs index aad578ce85..e140fa06e3 100644 --- a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/PEVAMTShiftStrategyTests.cs +++ b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/PEVAMTShiftStrategyTests.cs @@ -503,7 +503,7 @@ namespace TUGraz.Vecto.UnitTests.TestCases.Components.GearShiftStrategy container.Setup(r => r.RunData).Returns(runData); //EmInfo - var em = GetMockElectricMotor(container.Object, runData.ElectricMachinesData.Single().Item2); + var em = GetElectricMotor(container.Object, runData.ElectricMachinesData.Single().Item2); container.Setup(c => c.ElectricMotorInfo(PowertrainPosition.BatteryElectricE2)) .Returns(em); container.Setup(c => c.PowertrainInfo.ElectricMotorPositions).Returns(new[] { @@ -529,6 +529,12 @@ namespace TUGraz.Vecto.UnitTests.TestCases.Components.GearShiftStrategy //PowertrainBuilder, SimplePowertrain var testPt = GetTestPowertrain(ratios, container, out _); var ptBuilder = new Mock<ISimplePowertrainBuilder>(); + ptBuilder.Setup(c => c.CreateTestPowertrain( + It.IsAny<IVehicleContainer>(), It.IsAny<bool>())) + .Returns(testPt.Object); + ptBuilder.Setup(c => c.CreateTestPowertrain( + It.IsAny<IVehicleContainer>(), It.IsAny<bool>(), It.IsAny<VectoSimulationJobType>())) + .Returns(testPt.Object); container.Setup(c => c.SimplePowertrainBuilder).Returns(ptBuilder.Object); //DrivingCycleInfo @@ -542,9 +548,23 @@ namespace TUGraz.Vecto.UnitTests.TestCases.Components.GearShiftStrategy out Mock<ISimpleVehicleContainer> simplePt) { var testPt = new Mock<ITestPowertrain>(); - - simplePt = GetSimplePowertrain(ratios, container); + simplePt = GetSimplePowertrain(ratios, container, out var gbx); + var simplePtObj = simplePt.Object; + testPt.Setup(t => t.ElectricMotors).Returns(() => { + var dict = new Dictionary<PowertrainPosition, ITestpowertrainElectricMotor>(); + foreach (var (k, v) in simplePtObj.ElectricMotors) { + if (v is ITestpowertrainElectricMotor testEm) { + dict[k] = testEm; + } else { + throw new Exception("Expected TestElectricMotor in simple powertrain"); + } + } + return dict; + }); + testPt.Setup(t => t.Container).Returns(simplePt.Object); + + testPt.Setup(t => t.Gearbox).Returns(gbx.Object); return testPt; } @@ -577,7 +597,7 @@ namespace TUGraz.Vecto.UnitTests.TestCases.Components.GearShiftStrategy return electricSystem; } - private ElectricMotor GetMockElectricMotor(IVehicleContainer container, ElectricMotorData emData) + private ElectricMotor GetElectricMotor(IVehicleContainer container, ElectricMotorData emData) { var emControl = new SimpleElectricMotorControl(); @@ -589,28 +609,51 @@ namespace TUGraz.Vecto.UnitTests.TestCases.Components.GearShiftStrategy electricMotor.Connect(es.Object); return electricMotor; } + + private TestPowertrainElectricMotor GetTestPowertrainElectricMotor(ISimpleVehicleContainer container, + ElectricMotorData emData) + { + var emControl = new SimpleElectricMotorControl(); + + var electricMotor = new TestPowertrainElectricMotor(container: container, emData, emControl, + PowertrainPosition.BatteryElectricE2); + + //Connect Electric System + var es = GetMockElectricSystem(); + electricMotor.Connect(es.Object); + return electricMotor; + } - private Mock<ISimpleVehicleContainer> GetSimplePowertrain(double[] ratios, Mock<IVehicleContainer> container) + private Mock<ISimpleVehicleContainer> GetSimplePowertrain( + double[] ratios, + Mock<IVehicleContainer> container, + out Mock<ITestPowertrainTransmission> testGbx) { var simplePt = new Mock<ISimpleVehicleContainer>(); - + simplePt.Setup(s => s.IsTestPowertrain).Returns(true); + + var components = new List<VectoSimulationComponent>(); var runData = container.Object.RunData; - var em = GetMockElectricMotor(container.Object, runData.ElectricMachinesData.Single().Item2); + var em = GetTestPowertrainElectricMotor(simplePt.Object, runData.ElectricMachinesData.Single().Item2); var emDict = new Dictionary<PowertrainPosition, IElectricMotorInfo>() { { PowertrainPosition.BatteryElectricE2, em }, }; simplePt.Setup(r => r.ElectricMotorInfo(PowertrainPosition.BatteryElectricE2)) .Returns(em); + //BatteryInfo + simplePt.Setup(s => s.BatteryInfo.InternalVoltage).Returns(700.SI<Volt>()); - simplePt.Setup(r => r.ElectricMotors).Returns(emDict); + simplePt.Setup(s => s.ElectricMotors).Returns(emDict); simplePt.Setup(s => s.PowertrainInfo.HasCombustionEngine).Returns(false); - simplePt.Setup(s => s.RunData).Returns(GetRunData(ratios)); + + simplePt.Setup(s => s.RunData).Returns(runData); - var testGbx = GetTestGearbox(simplePt.Object, em); + testGbx = GetTestGearbox(simplePt.Object, em, runData.GearboxData.Gears); + simplePt.Setup(s => s.GearboxCtl).Returns(testGbx.Object); simplePt.Setup(s => s.GearboxInfo).Returns(testGbx.Object); simplePt.Setup(s => s.GearboxOutPort).Returns(testGbx.Object); @@ -624,42 +667,45 @@ namespace TUGraz.Vecto.UnitTests.TestCases.Components.GearShiftStrategy return simplePt; } - - Mock<ITestPowertrainTransmission> GetTestGearbox(ISimpleVehicleContainer simpleContainer, ElectricMotor em) + + Mock<ITestPowertrainTransmission> GetTestGearbox( + ISimpleVehicleContainer simpleContainer, + TestPowertrainElectricMotor em, + Dictionary<uint, GearData> ratios) { Mock<IAMTGearbox> amtGearbox = new Mock<IAMTGearbox>(); amtGearbox.Name = "PEVAMT_TestGearbox"; Mock<ITestPowertrainTransmission> gbx = amtGearbox.As<ITestPowertrainTransmission>(); - - gbx.Setup(g => g.LastUpshift).Returns(-double.MaxValue.SI<Second>()); gbx.Setup(g => g.LastDownshift).Returns(-double.MaxValue.SI<Second>()); GearshiftPosition gear = null; - gbx.SetupGet(g => g.Gear).Returns(() => { - - return gear; - }); + gbx.SetupGet(g => g.Gear).Returns(() => gear); gbx.SetupSet(g => g.SetGear = It.IsAny<GearshiftPosition>()) .Callback<GearshiftPosition>(p => { gear = p; }); - + GearshiftPosition nextGear = null; gbx.SetupGet(g => g.NextGear).Returns(() => nextGear); gbx.SetupSet(g => g.SetNextGear = It.IsAny<GearshiftPosition>()) .Callback<GearshiftPosition>(p => nextGear = p); + gbx.Setup(p => p.Initialize(It.IsAny<NewtonMeter>(), - It.IsAny<PerSecond>())).Returns((NewtonMeter tq, PerSecond rpm) => { + It.IsAny<PerSecond>())).Returns((NewtonMeter outTorque, PerSecond outSpeed) => { + var ratio = + gbx.Object.Gear == null ? 1.0 : ratios[gbx.Object.Gear.Gear].Ratio; + + var inSpeed = outSpeed * ratio; + var inTorque = outTorque / ratio; + + em.Initialize(inTorque, inSpeed); return new ResponseSuccess(this) { - Engine = { - EngineSpeed = rpm, - PowerRequest = tq * rpm, - }, + }; }); gbx.Setup(p => p.Request( @@ -670,29 +716,43 @@ namespace TUGraz.Vecto.UnitTests.TestCases.Components.GearShiftStrategy true)).Returns(( Second absTime, Second dt, - NewtonMeter t, - PerSecond n, + NewtonMeter outTorque, + PerSecond outSpeed, bool dryRun) => { - + var ratio = gbx.Object.Gear == null ? 1.0 : ratios[gbx.Object.Gear.Gear].Ratio; + + var inSpeed = outSpeed * ratio; + var inTorque = outTorque / ratio; + + var emResponse = em.Request(absTime, dt, inTorque, inSpeed, dryRun); return dryRun - ? new ResponseDryRun(this) { - Engine = { - PowerRequest = n * t, EngineSpeed = n * ratio, - DynamicFullLoadPower = (t / ratio + 2300.SI<NewtonMeter>()) * n * ratio, - TotalTorqueDemand = t, + ? new ResponseDryRun(this, emResponse) { + // Engine = { + // PowerRequest = n * t, EngineSpeed = n * ratio, + // DynamicFullLoadPower = (t / ratio + 2300.SI<NewtonMeter>()) * n * ratio, + // TotalTorqueDemand = t, + // }, + // ElectricMotor = emResponse.ElectricMotor, + Gearbox = { + Gear = gbx.Object.Gear, + InputSpeed = inSpeed, + InputTorque = inTorque, + OutputSpeed = outSpeed, + OutputTorque = outTorque, + PowerRequest = outSpeed * outTorque, }, - Clutch = { PowerRequest = n * t }, - DeltaFullLoad = n * t / 2 * (-1) + Clutch = { PowerRequest = outSpeed * outTorque }, + DeltaFullLoad = outSpeed * outTorque / 2 * (-1) } : new ResponseSuccess(this) { - Engine = { - PowerRequest = n * t, - EngineSpeed = n * ratio - + Gearbox = { + Gear = gbx.Object.Gear, + InputSpeed = inSpeed, + InputTorque = inTorque, }, - Clutch = { PowerRequest = n * t } + Clutch = { PowerRequest = outSpeed * outTorque } }; }); return gbx; @@ -781,7 +841,7 @@ namespace TUGraz.Vecto.UnitTests.TestCases.Components.GearShiftStrategy foreach (var entry in gearboxData.Gears) { var gearIdx = (int)entry.Key - 1; var dynamicTyreRadius = 0.5.SI<Meter>(); - + var shiftPolygon = DeclarationData.Gearbox.ComputeElectricMotorShiftPolygon( gearIdx, emData, diff --git a/Testing/UnitTests/Vecto UnitTests/TestCases/DeclarationDataTests/GenericModelParams/GearShiftStrategy/PEV_ShiftLineTests.cs b/Testing/UnitTests/Vecto UnitTests/TestCases/DeclarationDataTests/GenericModelParams/GearShiftStrategy/PEV_ShiftLineTests.cs index a742c2ba91..d5a1e87e47 100644 --- a/Testing/UnitTests/Vecto UnitTests/TestCases/DeclarationDataTests/GenericModelParams/GearShiftStrategy/PEV_ShiftLineTests.cs +++ b/Testing/UnitTests/Vecto UnitTests/TestCases/DeclarationDataTests/GenericModelParams/GearShiftStrategy/PEV_ShiftLineTests.cs @@ -3,14 +3,18 @@ using NUnit.Framework; 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.Simulation; using TUGraz.VectoCore.Models.Simulation.Data; using TUGraz.VectoCore.Models.SimulationComponent.Data; using TUGraz.VectoCore.Models.SimulationComponent.Data.ElectricMotor; using TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox; +using TUGraz.VectoCore.Models.SimulationComponent.Impl; using TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies; using TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies.ShiftPolygonCalc; +using TUGraz.VectoCore.Tests.Utils; +using TUGraz.VectoCore.Utils; using Assert = NUnit.Framework.Assert; namespace TUGraz.Vecto.UnitTests.TestCases.DeclarationDataTests.GenericModelParams.GearShiftStrategy; @@ -18,6 +22,156 @@ namespace TUGraz.Vecto.UnitTests.TestCases.DeclarationDataTests.GenericModelPara public class PEV_ShiftLineTests { [TestCase] + public void ComputePEVShiftLinesADC() + { + var axlegearRatio = 2.64; + var r_dyn = 0.421.SI<Meter>(); + + var expectedDownshiftNoADC = new[] { + // Gear 1 + new Point[] { + + }, + // Gear 2 + new[] { + new Point(1969.345479169557, -1067), + new Point(1969.345479169557, -950.6), + new Point(253.98783622789142, -950.6), + new Point(253.98783622789142, 950.6), + new Point(2452.135493, 950.6), + new Point(2461.1589140000006, 950.6), + new Point(2466.8630340000004, 948.41362), + new Point(2481.590574, 942.781315), + new Point(2496.3181150000005, 937.220305), + new Point(2503.681885, 934.463565), + new Point(2539.878362278914, 921.3333994166501), + new Point(2539.878362278914, 1067), + }, + // Gear 3 + new[] { + new Point(1969.345479169557, -1067), + new Point(1969.345479169557, -950.6), + new Point(253.98783622789142, -950.6), + new Point(253.98783622789142, 950.6), + new Point(2452.135493, 950.6), + new Point(2461.1589140000006, 950.6), + new Point(2466.8630340000004, 948.41362), + new Point(2481.590574, 942.781315), + new Point(2496.3181150000005, 937.220305), + new Point(2503.681885, 934.463565), + new Point(2539.878362278914, 921.3333994166501), + new Point(2539.878362278914, 1067), + }, + }; + var expectedUpshiftNoADC = new[] { + // Gear 1 + new[] { + new Point(6627.393225000001, 1067), + new Point(6627.393225000001, -1067), + }, + // Gear 2 + new[] { + new Point(6627.393225000001, 1067), + new Point(6627.393225000001, -1067), + }, + // Gear 3 + new[] { + new Point(6627.393225000001, 1067), + new Point(6627.393225000001, -1067), + }, + }; + var countEm = 2; + var emRatio = 2.0; + + var expectedUpshift = + expectedUpshiftNoADC.Select(ps => ps.Select(p => new Point(p.X / emRatio, p.Y * emRatio)).ToArray()).ToArray(); + var expectedDownshift = + expectedDownshiftNoADC.Select(ps => ps.Select(p => new Point(p.X / emRatio, p.Y * emRatio)).ToArray()).ToArray(); + + + + var emFld = new ElectricMotorFullLoadCurve(EM_FullLoad_125kW_485Nm.Select(x => + new ElectricMotorFullLoadCurve.FullLoadEntry() { + // invert motor full load curve here as would be done in respective reader class + MotorSpeed = x[0].RPMtoRad(), + FullDriveTorque = -x[1].SI<NewtonMeter>() * countEm, + FullGenerationTorque = -x[2].SI<NewtonMeter>() * countEm, + }).ToList()); + + var emEffMap = GetEffMap(emFld, countEm); + + + + + var emData = new ElectricMotorData() { + EfficiencyData = new VoltageLevelData() { + VoltageLevels = new List<ElectricMotorVoltageLevelData>() { + new ElectricMotorVoltageLevelData() { + FullLoadCurve = emFld, + EfficiencyMap = emEffMap, + } + } + }, + TransmissionLossMap = TransmissionLossMapReader.CreateEmADCLossMap(1, emRatio, "ADC"), + RatioADC = emRatio + }; + var gearboxData = new Mock<IGearboxEngineeringInputData>().Object; + var gear = new Mock<ITransmissionInputData>().Object; + Mock.Get(gearboxData).Setup(g => g.Gears).Returns(new List<ITransmissionInputData>() { + gear, gear, gear, gear, gear, gear, gear, gear, gear, gear, gear, gear, + }); + + var shiftPolygons = new List<ShiftPolygon>(); + + var shiftStrategyParams = new ShiftStrategyParameters(); // use default (declaration) shift strategy params + // var downshiftMaxSpeed = emFld.RatedSpeed * shiftStrategyParams.PEV_DownshiftSpeedFactor.LimitTo(0, 1); + // var downshiftMinSpeed = emFld.RatedSpeed * shiftStrategyParams.PEV_DownshiftMinSpeedFactor; + + + + for (var i = 0; i < gearboxData.Gears.Count; i++) { + var shiftPolygon = DeclarationData.Gearbox.ComputeElectricMotorShiftPolygon( + i, + emData, + gearboxData.Gears, + shiftStrategyParams.PEV_DownshiftSpeedFactor.LimitTo(0,1), + shiftStrategyParams.PEV_DownshiftMinSpeedFactor + ); + + // var shiftpolygon = DeclarationData.Gearbox.ComputeElectricMotorShiftPolygon(i, + // emFld, emRatio, + // gearboxData.Gears, + // axlegearRatio, + // r_dyn, + // downshiftMaxSpeed, + // downshiftMinSpeed); + shiftPolygons.Add(shiftPolygon); + } + + + CommonSanityChecks(shiftPolygons, emData.EfficiencyData.MaxSpeed / emRatio); + + + for (var i = 0; i < Math.Min(gearboxData.Gears.Count, Math.Min(expectedDownshift.Length, expectedUpshift.Length)); i++) { + foreach (var tuple in expectedDownshift[i].Zip(shiftPolygons[i].Downshift, Tuple.Create)) { + Assert.AreEqual(tuple.Item1.X, tuple.Item2.AngularSpeed.AsRPM, 1e-3, "gear: {0} entry: {1}", i + 1, tuple); + Assert.AreEqual(tuple.Item1.Y, tuple.Item2.Torque.Value(), 1e-3, "gear: {0} entry: {1}", i + 1, tuple); + } + + foreach (var tuple in expectedUpshift[i].Zip(shiftPolygons[i].Upshift, Tuple.Create)) { + Assert.AreEqual(tuple.Item1.X, tuple.Item2.AngularSpeed.AsRPM, 1e-3, "gear: {0} entry: {1}", i + 1, tuple); + Assert.AreEqual(tuple.Item1.Y, tuple.Item2.Torque.Value(), 1e-3, "gear: {0} entry: {1}", i + 1, tuple); + } + } + + Assert.AreEqual(0, shiftPolygons.First().Downshift.Count); + Assert.AreEqual(0, shiftPolygons.Last().Upshift.Count); + + //var suffix = factorDownshiftSpeed.HasValue ? $"_{factorDownshiftSpeed.Value}" : ""; + + } + + [TestCase] public void ComputePEVShiftLines() { var axlegearRatio = 2.64; @@ -78,7 +232,7 @@ public class PEV_ShiftLineTests }; var countEm = 2; - var emRatio = 2.0; + var emRatio = 1.0; var emFld = new ElectricMotorFullLoadCurve(EM_FullLoad_125kW_485Nm.Select(x => new ElectricMotorFullLoadCurve.FullLoadEntry() { @@ -88,6 +242,23 @@ public class PEV_ShiftLineTests FullGenerationTorque = -x[2].SI<NewtonMeter>() * countEm, }).ToList()); + var emEffMap = GetEffMap(emFld, countEm); + + + + + var emData = new ElectricMotorData() { + EfficiencyData = new VoltageLevelData() { + VoltageLevels = new List<ElectricMotorVoltageLevelData>() { + new ElectricMotorVoltageLevelData() { + FullLoadCurve = emFld, + EfficiencyMap = emEffMap, + } + } + }, + TransmissionLossMap = TransmissionLossMapReader.CreateEmADCLossMap(1, emRatio, "ADC"), + RatioADC = emRatio + }; var gearboxData = new Mock<IGearboxEngineeringInputData>().Object; var gear = new Mock<ITransmissionInputData>().Object; Mock.Get(gearboxData).Setup(g => g.Gears).Returns(new List<ITransmissionInputData>() { @@ -97,14 +268,33 @@ public class PEV_ShiftLineTests var shiftPolygons = new List<ShiftPolygon>(); var shiftStrategyParams = new ShiftStrategyParameters(); // use default (declaration) shift strategy params - var downshiftMaxSpeed = emFld.RatedSpeed * shiftStrategyParams.PEV_DownshiftSpeedFactor.LimitTo(0, 1); - var downshiftMinSpeed = emFld.RatedSpeed * shiftStrategyParams.PEV_DownshiftMinSpeedFactor; + // var downshiftMaxSpeed = emFld.RatedSpeed * shiftStrategyParams.PEV_DownshiftSpeedFactor.LimitTo(0, 1); + // var downshiftMinSpeed = emFld.RatedSpeed * shiftStrategyParams.PEV_DownshiftMinSpeedFactor; + + for (var i = 0; i < gearboxData.Gears.Count; i++) { - var shiftpolygon = DeclarationData.Gearbox.ComputeElectricMotorShiftPolygon(i, emFld, emRatio, gearboxData.Gears, axlegearRatio, r_dyn, downshiftMaxSpeed, downshiftMinSpeed); - shiftPolygons.Add(shiftpolygon); + var shiftPolygon = DeclarationData.Gearbox.ComputeElectricMotorShiftPolygon( + i, + emData, + gearboxData.Gears, + shiftStrategyParams.PEV_DownshiftSpeedFactor.LimitTo(0,1), + shiftStrategyParams.PEV_DownshiftMinSpeedFactor + ); + + // var shiftpolygon = DeclarationData.Gearbox.ComputeElectricMotorShiftPolygon(i, + // emFld, emRatio, + // gearboxData.Gears, + // axlegearRatio, + // r_dyn, + // downshiftMaxSpeed, + // downshiftMinSpeed); + shiftPolygons.Add(shiftPolygon); } + + CommonSanityChecks(shiftPolygons, emData.EfficiencyData.MaxSpeed / emRatio); + for (var i = 0; i < Math.Min(gearboxData.Gears.Count, Math.Min(expectedDownshift.Length, expectedUpshift.Length)); i++) { foreach (var tuple in expectedDownshift[i].Zip(shiftPolygons[i].Downshift, Tuple.Create)) { Assert.AreEqual(tuple.Item1.X, tuple.Item2.AngularSpeed.AsRPM, 1e-3, "gear: {0} entry: {1}", i + 1, tuple); @@ -124,7 +314,339 @@ public class PEV_ShiftLineTests } - [TestCase] + + + [TestCase] + public void ComputePEVShiftLinesDeratedSanity() + { + var axlegearRatio = 2.64; + var r_dyn = 0.421.SI<Meter>(); + + var expectedDownshift = new[] { + // Gear 1 + new Point[] { + + }, + // Gear 2 + new[] { + new Point(1969.345479169557, -1067), + new Point(1969.345479169557, -950.6), + new Point(253.98783622789142, -950.6), + new Point(253.98783622789142, 950.6), + new Point(2452.135493, 950.6), + new Point(2461.1589140000006, 950.6), + new Point(2466.8630340000004, 948.41362), + new Point(2481.590574, 942.781315), + new Point(2496.3181150000005, 937.220305), + new Point(2503.681885, 934.463565), + new Point(2539.878362278914, 921.3333994166501), + new Point(2539.878362278914, 1067), + }, + // Gear 3 + new[] { + new Point(1969.345479169557, -1067), + new Point(1969.345479169557, -950.6), + new Point(253.98783622789142, -950.6), + new Point(253.98783622789142, 950.6), + new Point(2452.135493, 950.6), + new Point(2461.1589140000006, 950.6), + new Point(2466.8630340000004, 948.41362), + new Point(2481.590574, 942.781315), + new Point(2496.3181150000005, 937.220305), + new Point(2503.681885, 934.463565), + new Point(2539.878362278914, 921.3333994166501), + new Point(2539.878362278914, 1067), + }, + }; + var expectedUpshift = new[] { + // Gear 1 + new[] { + new Point(6627.393225000001, 1067), + new Point(6627.393225000001, -1067), + }, + // Gear 2 + new[] { + new Point(6627.393225000001, 1067), + new Point(6627.393225000001, -1067), + }, + // Gear 3 + new[] { + new Point(6627.393225000001, 1067), + new Point(6627.393225000001, -1067), + }, + }; + + var countEm = 2; + var emRatio = 1.0; + + var emFld = new ElectricMotorFullLoadCurve(EM_FullLoad_125kW_485Nm.Select(x => + new ElectricMotorFullLoadCurve.FullLoadEntry() { + // invert motor full load curve here as would be done in respective reader class + MotorSpeed = x[0].RPMtoRad(), + FullDriveTorque = -x[1].SI<NewtonMeter>() * countEm, + FullGenerationTorque = -x[2].SI<NewtonMeter>() * countEm, + }).ToList()); + + var emEffMap = GetEffMap(emFld, countEm); + + + + var continuousTorque = emFld.MaxGenerationTorque; + var emData = new ElectricMotorData() { + Overload = new OverloadData() { + ContinuousTorque = continuousTorque, + }, + EfficiencyData = new VoltageLevelData() { + VoltageLevels = new List<ElectricMotorVoltageLevelData>() { + new ElectricMotorVoltageLevelData() { + FullLoadCurve = emFld, + EfficiencyMap = emEffMap, + } + } + }, + TransmissionLossMap = TransmissionLossMapReader.CreateEmADCLossMap(1, emRatio, "ADC"), + RatioADC = emRatio + }; + var gearboxData = new Mock<IGearboxEngineeringInputData>().Object; + var gear = new Mock<ITransmissionInputData>().Object; + Mock.Get(gearboxData).Setup(g => g.Gears).Returns(new List<ITransmissionInputData>() { + gear, gear, gear, gear, gear, gear, gear, gear, gear, gear, gear, gear, + }); + + var shiftPolygons = new List<ShiftPolygon>(); + var runData = new VectoRunData() { GearshiftParameters = new ShiftStrategyParameters() }; + var container = new Mock<IVehicleContainer>(); + container.Setup(c => c.RunData).Returns(runData); + // var shiftStrategy = new PEVAMTShiftStrategy(container.Object); + // var deRatedShiftLines = shiftStrategy.CalculateDeratedShiftLines(emData, gearboxData.Gears, + // r_dyn, axlegearRatio, GearboxType.AMT); + + var shiftStrategy = new PEVAMTShiftStrategyPolygonCreator(runData.GearshiftParameters); + //var deRatedShiftLines = shiftStrategy.CalculateDeratedShiftLines(emData, gearboxData.Gears, + // r_dyn, axlegearRatio, GearboxType.AMT); + + for (var i = 0; i < gearboxData.Gears.Count; i++) { + //var emFld = emData.EfficiencyData.VoltageLevels.First().FullLoadCurve; + var contTq = emData.Overload.ContinuousTorque; + var limitedFld = DeclarationData.Gearbox.LimitElectricMotorFullLoadCurve(emFld, contTq); + var limitedEm = new ElectricMotorData() { + EfficiencyData = new VoltageLevelData() { + VoltageLevels = new List<ElectricMotorVoltageLevelData>() { + new DeratedVoltageLevelData(emFld.MaxSpeed) { + FullLoadCurve = limitedFld + } + } + }, + RatioADC = emData.RatioADC, + }; + + var deratedShiftLine = shiftStrategy.ComputeElectricMotorDeclarationShiftPolygon(GearboxType.APTN, i, + gearboxData.Gears, axlegearRatio, r_dyn, emData, limitedEm); + shiftPolygons.Add(deratedShiftLine); + } + + + CommonSanityChecks(shiftPolygons, emData.EfficiencyData.MaxSpeed / emRatio); + + for (var i = 0; i < Math.Min(gearboxData.Gears.Count, Math.Min(expectedDownshift.Length, expectedUpshift.Length)); i++) { + foreach (var tuple in expectedDownshift[i].Zip(shiftPolygons[i].Downshift, Tuple.Create)) { + Assert.AreEqual(tuple.Item1.X, tuple.Item2.AngularSpeed.AsRPM, 1e-3, "gear: {0} entry: {1}", i + 1, tuple); + Assert.AreEqual(tuple.Item1.Y, tuple.Item2.Torque.Value(), 1e-3, "gear: {0} entry: {1}", i + 1, tuple); + } + + foreach (var tuple in expectedUpshift[i].Zip(shiftPolygons[i].Upshift, Tuple.Create)) { + Assert.AreEqual(tuple.Item1.X, tuple.Item2.AngularSpeed.AsRPM, 1e-3, "gear: {0} entry: {1}", i + 1, tuple); + Assert.AreEqual(tuple.Item1.Y, tuple.Item2.Torque.Value(), 1e-3, "gear: {0} entry: {1}", i + 1, tuple); + } + } + + Assert.AreEqual(0, shiftPolygons.First().Downshift.Count); + Assert.AreEqual(0, shiftPolygons.Last().Upshift.Count); + + //var suffix = factorDownshiftSpeed.HasValue ? $"_{factorDownshiftSpeed.Value}" : ""; + + } + + + + [TestCase] + public void ComputePEVShiftLinesDeratedSanityADC() + { + var axlegearRatio = 2.64; + var r_dyn = 0.421.SI<Meter>(); + + var expectedDownshiftNoADC = new[] { + // Gear 1 + new Point[] { + + }, + // Gear 2 + new[] { + new Point(1969.345479169557, -1067), + new Point(1969.345479169557, -950.6), + new Point(253.98783622789142, -950.6), + new Point(253.98783622789142, 950.6), + new Point(2452.135493, 950.6), + new Point(2461.1589140000006, 950.6), + new Point(2466.8630340000004, 948.41362), + new Point(2481.590574, 942.781315), + new Point(2496.3181150000005, 937.220305), + new Point(2503.681885, 934.463565), + new Point(2539.878362278914, 921.3333994166501), + new Point(2539.878362278914, 1067), + }, + // Gear 3 + new[] { + new Point(1969.345479169557, -1067), + new Point(1969.345479169557, -950.6), + new Point(253.98783622789142, -950.6), + new Point(253.98783622789142, 950.6), + new Point(2452.135493, 950.6), + new Point(2461.1589140000006, 950.6), + new Point(2466.8630340000004, 948.41362), + new Point(2481.590574, 942.781315), + new Point(2496.3181150000005, 937.220305), + new Point(2503.681885, 934.463565), + new Point(2539.878362278914, 921.3333994166501), + new Point(2539.878362278914, 1067), + }, + }; + var expectedUpshiftNoADC = new[] { + // Gear 1 + new[] { + new Point(6627.393225000001, 1067), + new Point(6627.393225000001, -1067), + }, + // Gear 2 + new[] { + new Point(6627.393225000001, 1067), + new Point(6627.393225000001, -1067), + }, + // Gear 3 + new[] { + new Point(6627.393225000001, 1067), + new Point(6627.393225000001, -1067), + }, + }; + + var countEm = 2; + var emRatio = 2.0; + + var expectedUpshift = + expectedUpshiftNoADC.Select(ps => ps.Select(p => new Point(p.X / emRatio, p.Y * emRatio)).ToArray()).ToArray(); + var expectedDownshift = + expectedDownshiftNoADC.Select(ps => ps.Select(p => new Point(p.X / emRatio, p.Y * emRatio)).ToArray()).ToArray(); + + + var emFld = new ElectricMotorFullLoadCurve(EM_FullLoad_125kW_485Nm.Select(x => + new ElectricMotorFullLoadCurve.FullLoadEntry() { + // invert motor full load curve here as would be done in respective reader class + MotorSpeed = x[0].RPMtoRad(), + FullDriveTorque = -x[1].SI<NewtonMeter>() * countEm, + FullGenerationTorque = -x[2].SI<NewtonMeter>() * countEm, + }).ToList()); + + var emEffMap = GetEffMap(emFld, countEm); + + + + var continuousTorque = emFld.MaxGenerationTorque; + var emData = new ElectricMotorData() { + Overload = new OverloadData() { + ContinuousTorque = continuousTorque, + }, + EfficiencyData = new VoltageLevelData() { + VoltageLevels = new List<ElectricMotorVoltageLevelData>() { + new ElectricMotorVoltageLevelData() { + FullLoadCurve = emFld, + EfficiencyMap = emEffMap, + } + } + }, + TransmissionLossMap = TransmissionLossMapReader.CreateEmADCLossMap(1, emRatio, "ADC"), + RatioADC = emRatio + }; + var gearboxData = new Mock<IGearboxEngineeringInputData>().Object; + var gear = new Mock<ITransmissionInputData>().Object; + Mock.Get(gearboxData).Setup(g => g.Gears).Returns(new List<ITransmissionInputData>() { + gear, gear, gear, gear, gear, gear, gear, gear, gear, gear, gear, gear, + }); + + var shiftPolygons = new List<ShiftPolygon>(); + var runData = new VectoRunData() { GearshiftParameters = new ShiftStrategyParameters() }; + var container = new Mock<IVehicleContainer>(); + container.Setup(c => c.RunData).Returns(runData); + + var polygonCreator = new PEVAMTShiftStrategyPolygonCreator(runData.GearshiftParameters); + //var deRatedShiftLines = shiftStrategy.CalculateDeratedShiftLines(emData, gearboxData.Gears, + // r_dyn, axlegearRatio, GearboxType.AMT); + + for (var i = 0; i < gearboxData.Gears.Count; i++) { + //var emFld = emData.EfficiencyData.VoltageLevels.First().FullLoadCurve; + var contTq = emData.Overload.ContinuousTorque; + var limitedFld = DeclarationData.Gearbox.LimitElectricMotorFullLoadCurve(emFld, contTq); + var limitedEm = new ElectricMotorData() { + EfficiencyData = new VoltageLevelData() { + VoltageLevels = new List<ElectricMotorVoltageLevelData>() { + new DeratedVoltageLevelData(emFld.MaxSpeed) { + FullLoadCurve = limitedFld + } + } + }, + RatioADC = emData.RatioADC, + }; + + var deratedShiftLine = polygonCreator.ComputeElectricMotorDeclarationShiftPolygon(GearboxType.APTN, i, + gearboxData.Gears, axlegearRatio, r_dyn, emData, limitedEm); + shiftPolygons.Add(deratedShiftLine); + } + + + CommonSanityChecks(shiftPolygons, emData.EfficiencyData.MaxSpeed / emRatio); + + for (var i = 0; i < Math.Min(gearboxData.Gears.Count, Math.Min(expectedDownshift.Length, expectedUpshift.Length)); i++) { + foreach (var tuple in expectedDownshift[i].Zip(shiftPolygons[i].Downshift, Tuple.Create)) { + Assert.AreEqual(tuple.Item1.X, tuple.Item2.AngularSpeed.AsRPM, 1e-3, "gear: {0} entry: {1}", i + 1, tuple); + Assert.AreEqual(tuple.Item1.Y, tuple.Item2.Torque.Value(), 1e-3, "gear: {0} entry: {1}", i + 1, tuple); + } + + foreach (var tuple in expectedUpshift[i].Zip(shiftPolygons[i].Upshift, Tuple.Create)) { + Assert.AreEqual(tuple.Item1.X, tuple.Item2.AngularSpeed.AsRPM, 1e-3, "gear: {0} entry: {1}", i + 1, tuple); + Assert.AreEqual(tuple.Item1.Y, tuple.Item2.Torque.Value(), 1e-3, "gear: {0} entry: {1}", i + 1, tuple); + } + } + + Assert.AreEqual(0, shiftPolygons.First().Downshift.Count); + Assert.AreEqual(0, shiftPolygons.Last().Upshift.Count); + + //var suffix = factorDownshiftSpeed.HasValue ? $"_{factorDownshiftSpeed.Value}" : ""; + + } + + + + private static EfficiencyMap GetEffMap(ElectricMotorFullLoadCurve emFld, int countEm) + { + var emEffMap = ElectricMotorMapReader.Create( + InputDataHelper.InputDataAsTableData( + "n [rpm] , T [Nm] , P_el [kW]", + $"0, {emFld.MaxDriveTorque.Value()}, 0", + $"0, {emFld.MaxGenerationTorque.Value()}, 0", + $"0, 0, 0", + $"{emFld.MaxSpeed.AsRPM / 3}, {emFld.MaxDriveTorque.Value()}, -300", + $"{emFld.MaxSpeed.AsRPM / 3}, {emFld.MaxGenerationTorque.Value()}, 750", + $"{emFld.MaxSpeed.AsRPM / 3}, 0, 100", + $"{emFld.MaxSpeed.AsRPM / 2}, {emFld.MaxDriveTorque.Value()}, -300", + $"{emFld.MaxSpeed.AsRPM / 2}, {emFld.MaxGenerationTorque.Value()}, 750", + $"{emFld.MaxSpeed.AsRPM / 2}, 0, 100", + $"{emFld.MaxSpeed.AsRPM}, {emFld.MaxDriveTorque.Value()}, -300", + $"{emFld.MaxSpeed.AsRPM}, {emFld.MaxGenerationTorque.Value()}, 750", + $"{emFld.MaxSpeed.AsRPM}, 0, 100" + ).ApplyFactor(ElectricMotorMapReader.Fields.PowerElectrical, 1E3), countEm, ExecutionMode.Declaration); + return emEffMap; + } + + [TestCase] public void ComputePEVShiftLinesDeRated() { @@ -312,7 +834,7 @@ public class PEV_ShiftLineTests // }); var countEm = 2; - var emRatio = 2.0; + var emRatio = 1.0; var continuousTorque = 145.SI<NewtonMeter>() * countEm; var emFld = new ElectricMotorFullLoadCurve(EM_FullLoad_125kW_485Nm.Select(x => new ElectricMotorFullLoadCurve.FullLoadEntry() { @@ -322,6 +844,9 @@ public class PEV_ShiftLineTests FullGenerationTorque = -x[2].SI<NewtonMeter>() * countEm, }).ToList()); + var emEffMap = GetEffMap(emFld: emFld, countEm: countEm); + + var emData = new ElectricMotorData() { RatioADC = emRatio, Overload = new OverloadData() { @@ -330,10 +855,12 @@ public class PEV_ShiftLineTests EfficiencyData = new VoltageLevelData() { VoltageLevels = new List<ElectricMotorVoltageLevelData>() { new ElectricMotorVoltageLevelData() { - FullLoadCurve = emFld + FullLoadCurve = emFld, + EfficiencyMap = emEffMap } } - } + }, + TransmissionLossMap = TransmissionLossMapReader.CreateEmADCLossMap(1, emRatio, "ADC") }; var gearboxData = new Mock<IGearboxEngineeringInputData>().Object; var gear = new Mock<ITransmissionInputData>().Object; @@ -358,9 +885,10 @@ public class PEV_ShiftLineTests var runData = new VectoRunData() { GearshiftParameters = new ShiftStrategyParameters() }; var container = new Mock<IVehicleContainer>(); container.Setup(c => c.RunData).Returns(runData); - var shiftStrategy = new PEVAMTShiftStrategyPolygonCreator(runData.GearshiftParameters); - //var deRatedShiftLines = shiftStrategy.CalculateDeratedShiftLines(emData, gearboxData.Gears, - // r_dyn, axlegearRatio, GearboxType.AMT); + + var polygonCreator = new PEVAMTShiftStrategyPolygonCreator(runData.GearshiftParameters); + //var deRatedShiftLines = shiftStrategy.CalculateDeratedShiftLines(emData, gearboxData.Gears, + // r_dyn, axlegearRatio, GearboxType.AMT); for (var i = 0; i < gearboxData.Gears.Count; i++) { //var emFld = emData.EfficiencyData.VoltageLevels.First().FullLoadCurve; @@ -369,7 +897,7 @@ public class PEV_ShiftLineTests var limitedEm = new ElectricMotorData() { EfficiencyData = new VoltageLevelData() { VoltageLevels = new List<ElectricMotorVoltageLevelData>() { - new ElectricMotorVoltageLevelData() { + new DeratedVoltageLevelData(emFld.MaxSpeed) { FullLoadCurve = limitedFld } } @@ -377,11 +905,14 @@ public class PEV_ShiftLineTests RatioADC = emData.RatioADC, }; - var deratedShiftLine = shiftStrategy.ComputeElectricMotorDeclarationShiftPolygon(GearboxType.APTN, i, + var deratedShiftLine = polygonCreator.ComputeElectricMotorDeclarationShiftPolygon(GearboxType.APTN, i, gearboxData.Gears, axlegearRatio, r_dyn, emData, limitedEm); shiftPolygons.Add(deratedShiftLine); - } + } + + CommonSanityChecks(shiftPolygons, emData.EfficiencyData.MaxSpeed / emRatio); + for (var i = 0; i < Math.Min(gearboxData.Gears.Count, Math.Min(expectedDownshift.Length, expectedUpshift.Length)); i++) { foreach (var tuple in expectedDownshift[i].Zip(shiftPolygons[i].Downshift, Tuple.Create)) { Assert.AreEqual(tuple.Item1.X, tuple.Item2.AngularSpeed.AsRPM, 1e-3, "gear: {0} entry: {1}", i + 1, tuple); @@ -477,4 +1008,30 @@ public class PEV_ShiftLineTests new[] { 7290.132548,163.736,-163.736 }, new[] { 7363.77025,162.099125,-162.099125 }, }; + + + + + private void CommonSanityChecks(IEnumerable<ShiftPolygon> shiftPolygons, PerSecond emMaxSpeed) + { + var polygonList = shiftPolygons.ToList(); + foreach (var upShiftPolygon in polygonList.Select(p => p.Upshift)) { + foreach (var entry in upShiftPolygon) { + Assert.Less(entry.AngularSpeed, emMaxSpeed ); + } + } + + foreach (var shiftPolygon in polygonList) { + var upshift = shiftPolygon.Upshift; + var downshift = shiftPolygon.Downshift; + if (upshift.Count > 0 && downshift.Count > 0) { + Assert.True(downshift.All(d => d.AngularSpeed.IsSmallerOrEqual(upshift.First().AngularSpeed))); + } + } + + + + + + } } diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/GearBoxDataAdapter.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/GearBoxDataAdapter.cs index dd9893ae6d..8e5c554882 100644 --- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/GearBoxDataAdapter.cs +++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/GearBoxDataAdapter.cs @@ -462,16 +462,19 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.SimulationComponen var limitedEm = new ElectricMotorData() { EfficiencyData = new VoltageLevelData() { VoltageLevels = new List<ElectricMotorVoltageLevelData>() { - new ElectricMotorVoltageLevelData() { + new DeratedVoltageLevelData(em.EfficiencyData.MaxSpeed) { FullLoadCurve = limitedFld } } }, RatioADC = em.RatioADC, }; - var deratedEmShiftPolygon = shiftPolygonCalculator.ComputeElectricMotorDeclarationShiftPolygon(gearbox.Type, (int)i, + var deratedEmShiftPolygon = shiftPolygonCalculator.ComputeElectricMotorDeclarationShiftPolygon( + gearbox.Type, (int)i, gearbox.Gears, axlegearRatio, - dynamicTyreRadius, em, limitedEm); + dynamicTyreRadius, + em, + limitedEm); return deratedEmShiftPolygon; //retVal[i + 1] = shiftPolygon; } @@ -611,7 +614,7 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.SimulationComponen var limitedEm = new ElectricMotorData() { EfficiencyData = new VoltageLevelData() { VoltageLevels = new List<ElectricMotorVoltageLevelData>() { - new ElectricMotorVoltageLevelData() { + new DeratedVoltageLevelData(em.EfficiencyData.MaxSpeed) { FullLoadCurve = limitedFld } } diff --git a/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs b/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs index 47f74e2345..968a959ba8 100644 --- a/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs +++ b/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs @@ -58,6 +58,7 @@ using TUGraz.VectoCore.Models.SimulationComponent.Data.ElectricComponents.Batter using TUGraz.VectoCore.Models.SimulationComponent.Impl; using TUGraz.VectoCore.OutputData; using Point = TUGraz.VectoCommon.Utils.Point; +using NLog.Fluent; using ElectricSystem = TUGraz.VectoCore.Models.Declaration.Auxiliaries.ElectricSystem; namespace TUGraz.VectoCore.Models.Declaration @@ -1063,40 +1064,108 @@ namespace TUGraz.VectoCore.Models.Declaration } } - - public static ShiftPolygon ComputeElectricMotorShiftPolygon(int gearIdx, - ElectricMotorFullLoadCurve fullLoadCurveOrig, double emRatio, IList<ITransmissionInputData> gears, - double axlegearRatio, Meter dynamicTyreRadius, PerSecond downshiftMaxSpeed = null, PerSecond downshiftMinSpeed = null) + + + public static ShiftPolygon ComputeElectricMotorShiftPolygon( + int gearIdx, + ElectricMotorData electricMotorData, + IList<ITransmissionInputData> gears, + double? downshiftMaxSpeedFactor = null, + double? downShiftMinSpeedFactor = null) { - var gbxMaxTq = gears[gearIdx].MaxTorque != null ? gears[gearIdx].MaxTorque / emRatio : null; - var gbxMaxSpeed = gears[gearIdx].MaxInputSpeed != null ? gears[gearIdx].MaxInputSpeed * emRatio : null; - + if ((downshiftMaxSpeedFactor != null && !downshiftMaxSpeedFactor.Value.IsBetween(0.0, 1.0)) || + downShiftMinSpeedFactor != null && !downShiftMinSpeedFactor.Value.IsBetween(0.0, 1.0)) { + throw new VectoException("Invalid downshift factors: must be between 0.0 and 1.0"); + } + + //EM FullloadCurve + var fullLoadCurveOrig = electricMotorData.EfficiencyData.VoltageLevels.First().FullLoadCurve; + + var emRatio = electricMotorData.RatioADC; + var lossMap = electricMotorData.TransmissionLossMap; + var emMaxSpeed = electricMotorData.EfficiencyData.MaxSpeed; + + //Transform EM Fullloadcurve to include ADC losses and ratio. Convert EM to Drivetrain + var fullLoadCurveTransformed = TransformFullLoadCurve(fullLoadCurveOrig, lossMap, emRatio); + var emMaxSpeedDt = emMaxSpeed / emRatio; + + + //From now on we are on the gbx_in side. + var gbxMaxTq = gears[gearIdx].MaxTorque != null ? gears[gearIdx].MaxTorque : null; + var gbxMaxSpeed = gears[gearIdx].MaxInputSpeed != null ? gears[gearIdx].MaxInputSpeed : null; + + var fullLoadCurve = gbxMaxTq == null - ? fullLoadCurveOrig - : LimitElectricMotorFullLoadCurve(fullLoadCurveOrig, gbxMaxTq); + ? fullLoadCurveTransformed + : LimitElectricMotorFullLoadCurve(fullLoadCurveTransformed, gbxMaxTq); + if (gears.Count < 2) { throw new VectoException("ComputeShiftPolygon needs at least 2 gears. {0} gears given.", gears.Count); } - + var downShift = new List<ShiftPolygon.ShiftPolygonEntry>(); var upShift = new List<ShiftPolygon.ShiftPolygonEntry>(); if (gearIdx > 0) { - var nMax = downshiftMaxSpeed ?? fullLoadCurve.NP80low; - var nMin = downshiftMinSpeed ?? 0.1 * fullLoadCurve.RatedSpeed; - - downShift.AddRange(DownshiftLineDrive(fullLoadCurve, fullLoadCurveOrig, nMin, fullLoadCurve.NP80low)); - downShift.AddRange(DownshiftLineDrag(fullLoadCurve, fullLoadCurveOrig, nMin, nMax)); - + var nMax = downshiftMaxSpeedFactor.HasValue + ? downshiftMaxSpeedFactor.Value * fullLoadCurve.RatedSpeed + : fullLoadCurve.NP80low; + + var nMin = downShiftMinSpeedFactor.HasValue + ? downShiftMinSpeedFactor.Value * fullLoadCurve.RatedSpeed + : fullLoadCurve.RatedSpeed * 0.1; + + downShift.AddRange(DownshiftLineDrive(fullLoadCurve, fullLoadCurveTransformed, nMin, fullLoadCurve.NP80low)); + downShift.AddRange(DownshiftLineDrag(fullLoadCurve, fullLoadCurveTransformed, nMin, nMax)); + } if (gearIdx >= gears.Count - 1) { - return new ShiftPolygon(downShift, upShift); + return new ShiftPolygon(TransformShiftPolygonEntries(downShift, emRatio, lossMap), TransformShiftPolygonEntries(upShift, emRatio, lossMap)); } + + upShift.Add(new ShiftPolygon.ShiftPolygonEntry(fullLoadCurve.MaxGenerationTorque * 1.1, VectoMath.Min(emMaxSpeedDt * 0.9, gbxMaxSpeed))); + upShift.Add(new ShiftPolygon.ShiftPolygonEntry(fullLoadCurve.MaxDriveTorque * 1.1, VectoMath.Min(emMaxSpeedDt * 0.9, gbxMaxSpeed))); + return new ShiftPolygon(TransformShiftPolygonEntries(downShift, emRatio, lossMap), TransformShiftPolygonEntries(upShift, emRatio, lossMap)); + } - upShift.Add(new ShiftPolygon.ShiftPolygonEntry(fullLoadCurve.MaxGenerationTorque * 1.1, VectoMath.Min(fullLoadCurve.MaxSpeed * 0.9, gbxMaxSpeed))); - upShift.Add(new ShiftPolygon.ShiftPolygonEntry(fullLoadCurve.MaxDriveTorque * 1.1, VectoMath.Min(fullLoadCurve.MaxSpeed * 0.9, gbxMaxSpeed))); - return new ShiftPolygon(downShift, upShift); + + /// <summary> + /// Transforms the shiftpolygons from em side to drivetrain side (= gearbox in), considering the ADC ratio and losses + /// </summary> + /// <param name="entries"></param> + /// <param name="emRatio"></param> + /// <param name="lossMap"></param> + /// <returns></returns> + private static IList<ShiftPolygon.ShiftPolygonEntry> TransformShiftPolygonEntries( + IEnumerable<ShiftPolygon.ShiftPolygonEntry> entries, double emRatio, TransmissionLossMap lossMap) + { + return entries.ToList(); } + private static ElectricMotorFullLoadCurve TransformFullLoadCurve(ElectricMotorFullLoadCurve emFld, + TransmissionLossMap lossMap, double ratioAdc) + { + var fldCurve = + new ElectricMotorFullLoadCurve( + emFld.FullLoadEntries.Select(e => { + var drive = lossMap.GetOutTorqueAndSpeed(e.MotorSpeed, e.FullDriveTorque); + var generation = lossMap.GetOutTorqueAndSpeed(e.MotorSpeed, e.FullGenerationTorque); + return new ElectricMotorFullLoadCurve.FullLoadEntry() { + FullDriveTorque = drive.outTorque, + FullGenerationTorque = generation.outTorque, + MotorSpeed = drive.outAngularVelocity + }; + } + ).ToList()); + + return fldCurve; + } + + /// <summary> + /// Limit the fullload curve to the max gearbox in torque + /// </summary> + /// <param name="emFld"></param> + /// <param name="maxTq"></param> + /// <returns></returns> public static ElectricMotorFullLoadCurve LimitElectricMotorFullLoadCurve(ElectricMotorFullLoadCurve emFld, NewtonMeter maxTq) { var contTqFld = new ElectricMotorFullLoadCurve(new List<ElectricMotorFullLoadCurve.FullLoadEntry>() { diff --git a/VectoCore/VectoCore/Models/Simulation/DataBus/IElectricMotorInfo.cs b/VectoCore/VectoCore/Models/Simulation/DataBus/IElectricMotorInfo.cs index 59cde098fc..6d16bced64 100644 --- a/VectoCore/VectoCore/Models/Simulation/DataBus/IElectricMotorInfo.cs +++ b/VectoCore/VectoCore/Models/Simulation/DataBus/IElectricMotorInfo.cs @@ -12,7 +12,8 @@ namespace TUGraz.VectoCore.Models.Simulation.DataBus PerSecond ElectricMotorSpeed { get; } NewtonMeter ElectricMotorTorque { get; } PowertrainPosition Position { get; } - PerSecond MaxSpeed { get; } + PerSecond MaxSpeedDt { get; } + PerSecond RatedSpeedDt { get; } Watt DragPower(Volt volt, PerSecond electricMotorSpeed, GearshiftPosition gear); Watt MaxPowerDrive(Volt volt, PerSecond inAngularVelocity, GearshiftPosition gear); NewtonMeter GetTorqueForElectricPower(Volt volt, Watt electricPower, PerSecond avgEmSpeed, Second dt, GearshiftPosition gear, bool allowExtrapolation); diff --git a/VectoCore/VectoCore/Models/Simulation/PowertrainComponentNinjectModule.cs b/VectoCore/VectoCore/Models/Simulation/PowertrainComponentNinjectModule.cs index 243fb2574b..9de7660fc8 100644 --- a/VectoCore/VectoCore/Models/Simulation/PowertrainComponentNinjectModule.cs +++ b/VectoCore/VectoCore/Models/Simulation/PowertrainComponentNinjectModule.cs @@ -147,7 +147,7 @@ namespace TUGraz.VectoCore.Models.Simulation } Bind<IElectricSystem>().To<TestpowertrainElectricSystem>().Named(_testPowertrain.Prefix); Bind<IElectricChargerPort>().To<TestpowertrainGensetChargerAdapter>().Named(_testPowertrain.Prefix); - Bind<IElectricMotor>().To<TestpowertrainElectricMotor>().Named(_testPowertrain.ElectricMotorName(false)); + Bind<IElectricMotor>().To<TestPowertrainElectricMotor>().Named(_testPowertrain.ElectricMotorName(false)); Bind<IElectricMotor>().To<TestpowertrainIEPC>().Named(_testPowertrain.ElectricMotorName(true)); Bind<IElectricMotorControl>().To<SimpleElectricMotorControl>().Named(_testPowertrain.ElectricMotorControllerName(CycleType.DistanceBased)); diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Data/ElectricComponents/ElectricMotor/ElectricMotorData.cs b/VectoCore/VectoCore/Models/SimulationComponent/Data/ElectricComponents/ElectricMotor/ElectricMotorData.cs index 3f5056383b..41192481b7 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Data/ElectricComponents/ElectricMotor/ElectricMotorData.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Data/ElectricComponents/ElectricMotor/ElectricMotorData.cs @@ -244,6 +244,36 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data { } + + public class DeratedVoltageLevelData : ElectricMotorVoltageLevelData + { + public DeratedVoltageLevelData(PerSecond maxSpeed) + { + _maxSpeed = maxSpeed; + } + + #region Overrides of ElectricMotorVoltageLevelData + public override EfficiencyMap.EfficiencyResult LookupElectricPower(PerSecond avgSpeed, NewtonMeter torque, uint gear, bool allowExtrapolation) + { + throw new NotImplementedException(); + } + public override NewtonMeter LookupTorque(Watt electricPower, PerSecond avgSpeed, NewtonMeter maxEmTorque, uint gear) + { + throw new NotImplementedException(); + } + public override NewtonMeter FullLoadDriveTorque(PerSecond avgSpeed) + { + throw new NotImplementedException(); + } + public override NewtonMeter FullGenerationTorque(PerSecond avgSpeed) + { + throw new NotImplementedException(); + } + + #endregion + } + + public class OverloadData { diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/ShiftPolygon.cs b/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/ShiftPolygon.cs index d9f07a5528..39e0170128 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/ShiftPolygon.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/ShiftPolygon.cs @@ -47,10 +47,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox private readonly List<ShiftPolygonEntry> _upShiftPolygon; private readonly List<ShiftPolygonEntry> _downShiftPolygon; - internal ShiftPolygon(List<ShiftPolygonEntry> downshift, List<ShiftPolygonEntry> upShift) + internal ShiftPolygon(IList<ShiftPolygonEntry> downshift, IList<ShiftPolygonEntry> upShift) { - _upShiftPolygon = upShift; - _downShiftPolygon = downshift; + _upShiftPolygon = upShift.ToList(); + _downShiftPolygon = downshift.ToList(); } [JsonIgnore] diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TransmissionLossMap.cs b/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TransmissionLossMap.cs index 197feb4516..7eee96a5a1 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TransmissionLossMap.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TransmissionLossMap.cs @@ -45,8 +45,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox { [ValidateObject] internal readonly IReadOnlyList<GearLossMapEntry> _entries; - private readonly double _ratio; - /// <summary> /// The Loss map. [X=Output EngineSpeed, Y=Output Torque] => Z=Torque Loss /// </summary> @@ -59,6 +57,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox public string GearName { get; private set; } + public double Ratio { get; } public string[] LossMapSerialized @@ -69,7 +68,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox public TransmissionLossMap(IReadOnlyList<GearLossMapEntry> entries, double gearRatio, string gearName, bool createInnvertedMap) { GearName = gearName; - _ratio = gearRatio; + Ratio = gearRatio; _entries = entries; _lossMap = new DelaunayMap("TransmissionLossMap " + GearName); _invertedLossMap = createInnvertedMap ? new DelaunayMap("TransmissionLossMapInv. " + GearName) : null; @@ -91,10 +90,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox public LossMapResult GetTorqueLoss(PerSecond outAngularVelocity, NewtonMeter outTorque) { var result = new LossMapResult(); - var torqueLoss = _lossMap.Interpolate(outAngularVelocity.Value() * _ratio, outTorque.Value() / _ratio); + var torqueLoss = _lossMap.Interpolate(outAngularVelocity.Value() * Ratio, outTorque.Value() / Ratio); if (torqueLoss.IsNaN()) { - torqueLoss = _lossMap.Extrapolate(outAngularVelocity.Value() * _ratio, outTorque.Value() / _ratio); + torqueLoss = _lossMap.Extrapolate(outAngularVelocity.Value() * Ratio, outTorque.Value() / Ratio); result.Extrapolated = true; } @@ -111,6 +110,47 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox public bool Extrapolated; public NewtonMeter Value; } + /// <summary> + /// Computes the OUTPUT torque and speed given by the input speed and input torque + /// </summary> + /// <param name="inAngularVelocity"></param> + /// <param name="inTorque"></param> + /// <param name="allowExtrapolation"></param> + /// <returns></returns> + public (NewtonMeter outTorque, PerSecond outAngularVelocity) GetOutTorqueAndSpeed(PerSecond inAngularVelocity, + NewtonMeter inTorque, bool allowExtrapolation = false) + { + var outTorque = this.GetOutTorque(inAngularVelocity, inTorque, allowExtrapolation); + var outAngularVelocity = inAngularVelocity / Ratio; + + var torqueLoss = this.GetTorqueLoss(outAngularVelocity, outTorque); + var inTorqueBackward = GetInTorque(outAngularVelocity, outTorque); + + if(!inTorque.IsEqual(inTorqueBackward, 1E-8.SI<NewtonMeter>())) + { + Log.Debug($"{nameof(TransmissionLossMap)}: Forward Calculation and Backward Calculation of DriveTorque do not match..."); + //Search outTorque: + Log.Debug("Forward Calculation and Backward Calculation do not match..."); + outTorque = SearchAlgorithm.Search(inTorque, (inTorqueBackward - inTorque) * 1e3, outTorque / 10, + getYValue: r => ((r as NewtonMeter) - inTorque) * 1e3, + evaluateFunction: x => GetInTorque(outAngularVelocity, x), + criterion: r => { + var i = r as NewtonMeter; + return (i - inTorque).Value() * 1e3; + }, + searcher: this); + } + + return (outTorque, outAngularVelocity); + } + + public NewtonMeter GetInTorque(PerSecond outAngularVelocity, NewtonMeter outTorque) + { + var torqueLoss = this.GetTorqueLoss(outAngularVelocity, outTorque); + var inTorque = outTorque / Ratio + torqueLoss.Value; + return inTorque; + } + /// <summary> /// Computes the OUTPUT torque given by the input engineSpeed and the input torque. @@ -126,12 +166,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox } var torqueLoss = _invertedLossMap.Interpolate(inAngularVelocity.Value(), inTorque.Value()); if (!torqueLoss.IsNaN()) { - return (inTorque - torqueLoss.SI<NewtonMeter>()) * _ratio; + return (inTorque - torqueLoss.SI<NewtonMeter>()) * Ratio; } if (allowExtrapolation) { torqueLoss = _invertedLossMap.Extrapolate(inAngularVelocity.Value(), inTorque.Value()); - return (inTorque - torqueLoss.SI<NewtonMeter>()) * _ratio; + return (inTorque - torqueLoss.SI<NewtonMeter>()) * Ratio; } throw new VectoException("TransmissionLossMap {0}: Interpolation failed. inTorque: {1}, inAngularVelocity: {2}", diff --git a/VectoCore/VectoCore/Models/SimulationComponent/ITestPowertrain.cs b/VectoCore/VectoCore/Models/SimulationComponent/ITestPowertrain.cs index e3add8c86b..f4121fd0f0 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/ITestPowertrain.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/ITestPowertrain.cs @@ -29,8 +29,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent IBrakes Brakes { get; } ITestpowertrainElectricMotor ElectricMotor { get; } - Dictionary<PowertrainPosition, ITestpowertrainElectricMotor> ElectricMotors { get; } - Dictionary<PowertrainPosition, IElectricMotor> ElectricMotorsUpstreamTransmission { get; } + Dictionary<PowertrainPosition, ITestpowertrainElectricMotor> ElectricMotors { get; } + Dictionary<PowertrainPosition, IElectricMotor> ElectricMotorsUpstreamTransmission { get; } IDCDCConverter DCDCConverter { get; } ITorqueConverter TorqueConverter { get; } ITestpowertrainGensetChargerAdapter Charger { get; } diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/ElectricMotor.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/ElectricMotor.cs index 56575e123e..5af085c3be 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/ElectricMotor.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/ElectricMotor.cs @@ -16,9 +16,9 @@ using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { - public class TestpowertrainElectricMotor : ElectricMotor, ITestpowertrainElectricMotor + public class TestPowertrainElectricMotor : ElectricMotor, ITestpowertrainElectricMotor { - public TestpowertrainElectricMotor(IVehicleContainer container, ElectricMotorData data, + public TestPowertrainElectricMotor(IVehicleContainer container, ElectricMotorData data, IElectricMotorControl control, PowertrainPosition position) : base(container, data, control, position, false) { if (!container.IsTestPowertrain) { @@ -52,7 +52,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl public IElectricMotorControl Control { get; } protected ElectricMotorData ModelData; private PerSecond _maxSpeed; - + private PerSecond _ratedSpeed; + protected internal Joule ThermalBuffer = 0.SI<Joule>(); @@ -92,12 +93,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl Log.Error("Overload buffer for thermal de-rating is zero or negative! Please check electric motor data!"); } } - public double[] TransmissionRatioPerGear { get; set; } - public PowertrainPosition Position { get; } - public PerSecond MaxSpeed => _maxSpeed ?? (_maxSpeed = ModelData.EfficiencyData.MaxSpeed / ModelData.RatioADC); - + public PerSecond MaxSpeedDt => _maxSpeed ?? (_maxSpeed = ModelData.EfficiencyData.MaxSpeed / ModelData.RatioADC); + public PerSecond RatedSpeedDt => _ratedSpeed ?? (_ratedSpeed = ModelData.EfficiencyData.VoltageLevels.First().FullLoadCurve.RatedSpeed / ModelData.RatioADC); public Watt DragPower(Volt volt, PerSecond electricMotorSpeed, GearshiftPosition gear) { return ModelData.DragCurveLookup(electricMotorSpeed, gear) * electricMotorSpeed; @@ -505,10 +504,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl protected virtual PerSecond GetMotorSpeedLimit(Second absTime) { if (DataBus.GearboxInfo == null || DataBus.GearboxInfo.Gear.Gear == 0) { - return MaxSpeed; + return MaxSpeedDt; } - return VectoMath.Min(DataBus.GearboxInfo.GetGearData(DataBus.GearboxInfo.Gear.Gear)?.MaxSpeed, MaxSpeed); + return VectoMath.Min(DataBus.GearboxInfo.GetGearData(DataBus.GearboxInfo.Gear.Gear)?.MaxSpeed, MaxSpeedDt); } private NewtonMeter GetMaxRecuperationTorque(Volt volt, Second dt, PerSecond avgSpeed, GearshiftPosition gear) diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Shiftstrategies/PEVAMTShiftStrategy.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Shiftstrategies/PEVAMTShiftStrategy.cs index 50bf9fb32d..54578edcb7 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Shiftstrategies/PEVAMTShiftStrategy.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Shiftstrategies/PEVAMTShiftStrategy.cs @@ -208,27 +208,34 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies GearshiftPosition currentGear, IResponse r) { var nextGear = currentGear; + var derated = r.ElectricMotor.DeRatingActive; // upshift - if (IsAboveUpShiftCurve(currentGear, inTorque, inAngularVelocity, r.ElectricMotor.DeRatingActive)) { + if (IsAboveUpShiftCurve(currentGear, inTorque, inAngularVelocity, derated)) { + + inTorque = null; + inAngularVelocity = null; + r = null; + nextGear = GearList.Successor(currentGear); - while (GearList.HasSuccessor(nextGear)) { // check skip gears nextGear = GearList.Successor(nextGear); - var response = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, nextGear); - - inAngularVelocity = response.ElectricMotor.AngularVelocity; - inTorque = response.ElectricMotor.PowerRequest / inAngularVelocity; + var nextResponse = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, nextGear); - var maxTorque = VectoMath.Min(-response.ElectricMotor.MaxDriveTorque, + var nextInAngularVelocity = nextResponse.Gearbox.InputSpeed; + var nextInTorque = nextResponse.Gearbox.InputTorque; + + var maxTorque = VectoMath.Min( + -nextResponse.ElectricMotor.MaxDriveTorque, //ADC considered !nextGear.Equals(GearList.First()) - ? GearboxModelData.Gears[nextGear.Gear].ShiftPolygon - .InterpolateDownshift(response.Engine.EngineSpeed) - : double.MaxValue.SI<NewtonMeter>()); - var reserve = 1 - inTorque / maxTorque; + ? GearboxModelData.Gears[nextGear.Gear].ShiftPolygon.InterpolateDownshift(nextInAngularVelocity) + : double.MaxValue.SI<NewtonMeter>() + ); + + var reserve = 1 - nextInTorque / maxTorque; if (reserve >= 0 /*ModelData.TorqueReserve */ && - IsAboveDownShiftCurve(nextGear, inTorque, inAngularVelocity, r.ElectricMotor.DeRatingActive)) { + IsAboveDownShiftCurve(nextGear, nextInTorque, nextInAngularVelocity, derated)) { continue; } @@ -249,7 +256,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies ) { return currentGear; } - + if (_shiftStrategyParameters.AllowedGearRangeFC == 0) { + return currentGear; + } + var vDrop = DataBus.VehicleInfo.VehicleSpeed - estimatedVelocityPostShift; var vehicleSpeedPostShift = DataBus.VehicleInfo.VehicleSpeed - vDrop * _shiftStrategyParameters.VelocityDropFactor; @@ -319,19 +329,17 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies if (!GearList.HasPredecessor(currentGear)) { return currentGear; } - - if (response.ElectricMotor.DeRatingActive) { - - } + var derated = response.ElectricMotor.DeRatingActive; // check with shiftline - if (response.ElectricMotor.TorqueRequestEmMap != null && IsBelowDownShiftCurve(currentGear, - response.ElectricMotor.TorqueRequestEmMap, - response.ElectricMotor.AngularVelocity, response.ElectricMotor.DeRatingActive)) { - - if (DataBus.DriverInfo.DriverBehavior == DrivingBehavior.Braking) { - var brakingGear = SelectBrakingGear(currentGear, response); - return brakingGear; - } + if (IsBelowDownShiftCurve(currentGear, inTorque, inAngularVelocity, derated)) { + inTorque = null; + inAngularVelocity = null; + + + if (DataBus.DriverInfo.DriverBehavior == DrivingBehavior.Braking) { + var brakingGear = SelectBrakingGear(currentGear, response); + return brakingGear; + } var nextGear = GearList.Predecessor(currentGear); if (SpeedTooHighForEngine(nextGear, outAngularVelocity)) { @@ -341,25 +349,33 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies while (GearList.HasPredecessor(nextGear)) { // check skip gears nextGear = GearList.Predecessor(nextGear); - var resp = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, nextGear); + var nextReponse = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, nextGear); - inAngularVelocity = resp.ElectricMotor.AngularVelocity; - inTorque = resp.ElectricMotor.PowerRequest / resp.ElectricMotor.AvgDrivetrainSpeed; - - if (IsAboveUpShiftCurve(nextGear, inTorque, inAngularVelocity, resp.ElectricMotor.DeRatingActive)) { + var nextInAngularVelocity = nextReponse.Gearbox.InputSpeed; + var nextInTorque = nextReponse.Gearbox.InputTorque; + + if (IsAboveUpShiftCurve(nextGear, nextInTorque, nextInAngularVelocity, derated)) { nextGear = GearList.Successor(nextGear); break; } - - var maxTorque = VectoMath.Min(resp.ElectricMotor.MaxDriveTorque == null ? null : - resp.ElectricMotor.MaxDriveTorque, - !nextGear.Equals(GearList.First()) - ? GearboxModelData.Gears[nextGear.Gear].ShiftPolygon - .InterpolateDownshift(resp.Engine.EngineSpeed) - : double.MaxValue.SI<NewtonMeter>()); - var reserve = 1 - inTorque / maxTorque; + + var maxDriveTorque = nextReponse.ElectricMotor.MaxDriveTorque; //Already on drivetrain side + + var isFirstGear = nextGear.Equals(GearList.First()); + + var maxTorque = VectoMath.Min( + (maxDriveTorque == null + ? null + : -maxDriveTorque + ), + (!isFirstGear + ? GearboxModelData.Gears[nextGear.Gear].ShiftPolygon.InterpolateDownshift(nextInAngularVelocity) + : double.MaxValue.SI<NewtonMeter>() + )); + var reserve = 1 - nextInTorque / maxTorque; if (reserve >= 0 /*ModelData.TorqueReserve */ && - IsBelowDownShiftCurve(nextGear, inTorque, inAngularVelocity, resp.ElectricMotor.DeRatingActive)) { + IsBelowDownShiftCurve(nextGear, nextInTorque, nextInAngularVelocity, derated)) { continue; } @@ -370,7 +386,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies return nextGear; } - + //Should not matter if calculated on gbx or em side. if (response.ElectricMotor.TorqueRequestEmMap != null && response.ElectricMotor.MaxRecuperationTorqueEM != null && response.ElectricMotor.TorqueRequestEmMap.IsEqual( @@ -385,14 +401,20 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies } private GearshiftPosition SelectBrakingGear(GearshiftPosition currentGear, IResponse response) - { + { var tmpGear = new GearshiftPosition(currentGear.Gear, currentGear.TorqueConverterLocked); var candidates = new Dictionary<GearshiftPosition, PerSecond>(); - var gbxOutSpeed = response.Engine.EngineSpeed / + + var gbxOutSpeed = response.Gearbox.InputSpeed / GearboxModelData.Gears[tmpGear.Gear].Ratio; + + var firstGear = GearList.Predecessor(currentGear, 1); var lastGear = GearList.Predecessor(currentGear, (uint)GearshiftParams.AllowedGearRangeFC); - var maxEmSpeed = DataBus.GetElectricMotors().First(x => x.Position != PowertrainPosition.GEN).MaxSpeed; + + var electricMotor = DataBus.GetElectricMotors().First(x => x.Position != PowertrainPosition.GEN); + var maxEmSpeedDt = electricMotor.MaxSpeedDt; //Drivetrain + foreach (var gear in GearList.IterateGears(firstGear, lastGear)) { var ratio = gear.IsLockedGear() ? GearboxModelData.Gears[gear.Gear].Ratio @@ -402,7 +424,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies continue; } - if (gbxInSpeed.IsGreater(maxEmSpeed)) { + if (gbxInSpeed.IsGreater(maxEmSpeedDt)) { continue; } candidates[gear] = gbxInSpeed; @@ -412,18 +434,20 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies return tmpGear; } - var ratedSpeed = VoltageLevels.VoltageLevels.First().FullLoadCurve.RatedSpeed; - var maxSpeedNorm = VoltageLevels.MaxSpeed / ratedSpeed; + + + var ratedSpeed = electricMotor.RatedSpeedDt; + var maxSpeedNorm = maxEmSpeedDt / ratedSpeed; var targetMotor = (_shiftStrategyParameters.PEV_TargetSpeedBrakeNorm * (maxSpeedNorm - 1) + 1) * ratedSpeed; - if (candidates.Any(x => x.Value > targetMotor / EMRatio && x.Value < VoltageLevels.MaxSpeed / EMRatio)) { - var best = candidates.Where(x => x.Value > targetMotor / EMRatio && x.Value < VoltageLevels.MaxSpeed / EMRatio) + if (candidates.Any(x => x.Value > targetMotor && x.Value < maxEmSpeedDt)) { + var best = candidates.Where(x => x.Value > targetMotor && x.Value < maxEmSpeedDt) .OrderBy(x => x.Value).First(); return best.Key; } - if (candidates.Any(x => x.Value < VoltageLevels.MaxSpeed / EMRatio)) - return candidates.Where(x => x.Value < VoltageLevels.MaxSpeed / EMRatio).MaxBy(x => x.Value).Key; + if (candidates.Any(x => x.Value < maxEmSpeedDt)) + return candidates.Where(x => x.Value < maxEmSpeedDt).MaxBy(x => x.Value).Key; else { return candidates.MaxBy(x => x.Value).Key; } @@ -439,14 +463,21 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies return currentGear; } + if (_shiftStrategyParameters.AllowedGearRangeFC == 0) { + return currentGear; + } + var results = new List<Tuple<GearshiftPosition, double>>(); foreach (var tryNextGear in GearList.IterateGears(GearList.Predecessor(currentGear), GearList.Predecessor(currentGear, (uint)_shiftStrategyParameters.AllowedGearRangeFC))) { var response = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, tryNextGear); - var inAngularVelocity = GearboxModelData.Gears[tryNextGear.Gear].Ratio * outAngularVelocity; - var inTorque = response.ElectricMotor.PowerRequest / inAngularVelocity; + // var inAngularVelocity = GearboxModelData.Gears[tryNextGear.Gear].Ratio * outAngularVelocity; + // var inTorque = response.ElectricMotor.PowerRequest / inAngularVelocity; + var inAngularVelocity = response.Gearbox.InputSpeed; + var inTorque = response.Gearbox.InputTorque; + if (IsAboveUpShiftCurve(tryNextGear, inTorque, inAngularVelocity, response.ElectricMotor.DeRatingActive)) { continue; } @@ -541,9 +572,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies Constants.SimulationSettings.MeasuredSpeedTargetTimeInterval, outTorque, outAngularVelocity, true); - var inAngularSpeed = outAngularVelocity * GearboxModelData.Gears[gear.Gear].Ratio; - var inTorque = response.ElectricMotor.PowerRequest / inAngularSpeed; + // var inAngularSpeed = outAngularVelocity * GearboxModelData.Gears[gear.Gear].Ratio; + // var inTorque = response.Gearbox.PowerRequest / inAngularSpeed; + var inAngularSpeed = response.Gearbox.InputSpeed; + var inTorque = response.Gearbox.InputTorque; + // if in shift curve and torque reserve is provided: return the current gear if (!IsBelowDownShiftCurve(gear, inTorque, inAngularSpeed, false) && !IsAboveUpShiftCurve(gear, inTorque, inAngularSpeed, false)) { _nextGear = gear; @@ -700,7 +734,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies { return (outAngularSpeed * GearboxModelData.Gears[gear.Gear].Ratio).IsGreaterOrEqual(VectoMath.Min(GearboxModelData.Gears[gear.Gear].MaxSpeed, - DataBus.ElectricMotorInfo(EMPos).MaxSpeed)); + DataBus.ElectricMotorInfo(EMPos).MaxSpeedDt)); } public void Disengage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity) { } diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Shiftstrategies/ShiftPolygonCalc/PEVAMTShiftStrategyPolygonCreator.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Shiftstrategies/ShiftPolygonCalc/PEVAMTShiftStrategyPolygonCreator.cs index e71334c296..f5827b0549 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Shiftstrategies/ShiftPolygonCalc/PEVAMTShiftStrategyPolygonCreator.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Shiftstrategies/ShiftPolygonCalc/PEVAMTShiftStrategyPolygonCreator.cs @@ -35,21 +35,26 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies.Shift throw new NotImplementedException("Not applicable to PEVAMT Gearbox."); } - public ShiftPolygon ComputeDeclarationShiftPolygon(GearboxType gearboxType, int i, EngineFullLoadCurve engineDataFullLoadCurve, - IList<ITransmissionInputData> gearboxGears, CombustionEngineData engineData, double axlegearRatio, Meter dynamicTyreRadius, - ElectricMotorData electricMotorData = null) - { - if (electricMotorData == null) { - throw new VectoException("ElectricMotorData is required to calculate Shift Polygon!"); - } - var emFld = electricMotorData.EfficiencyData.VoltageLevels.First().FullLoadCurve; + public ShiftPolygon ComputeDeclarationShiftPolygon(GearboxType gearboxType, int i, EngineFullLoadCurve engineDataFullLoadCurve, + IList<ITransmissionInputData> gearboxGears, CombustionEngineData engineData, double axlegearRatio, Meter dynamicTyreRadius, + ElectricMotorData electricMotorData = null) + { + if (electricMotorData == null) + { + throw new VectoException("ElectricMotorData is required to calculate Shift Polygon!"); + } + var emFld = electricMotorData.EfficiencyData.VoltageLevels.First().FullLoadCurve; + return ComputeDeclarationShiftPolygon(i, gearboxGears, axlegearRatio, dynamicTyreRadius, electricMotorData, + _shiftStrategyParameters.PEV_DownshiftSpeedFactor.LimitTo(0, 1), _shiftStrategyParameters.PEV_DownshiftMinSpeedFactor); + } + + public ShiftPolygon ComputeDeclarationShiftPolygon(int i, + IList<ITransmissionInputData> gearboxGears, double axlegearRatio, + Meter dynamicTyreRadius, + ElectricMotorData electricMotorData, double? downshiftMaxSpeed, double? downshiftMinSpeed) + { return DeclarationData.Gearbox.ComputeElectricMotorShiftPolygon(i, - electricMotorData.EfficiencyData.VoltageLevels.First().FullLoadCurve, - electricMotorData.RatioADC, gearboxGears, axlegearRatio, dynamicTyreRadius, - _shiftStrategyParameters.PEV_DownshiftSpeedFactor.LimitTo(0, 1) * emFld.RatedSpeed, - _shiftStrategyParameters.PEV_DownshiftMinSpeedFactor * emFld.RatedSpeed); - //return ComputeElectricMotorDeclarationShiftPolygon(gearboxType, i, gearboxGears, axlegearRatio, dynamicTyreRadius, electricMotorData, - // _shiftStrategyParameters.PEV_DownshiftSpeedFactor.LimitTo(0, 1) * emFld.RatedSpeed, _shiftStrategyParameters.PEV_DownshiftMinSpeedFactor * emFld.RatedSpeed); + electricMotorData, gearboxGears, downshiftMaxSpeed, downshiftMinSpeed); } @@ -57,13 +62,22 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies.Shift IList<ITransmissionInputData> gearboxGears, double axlegearRatio, Meter dynamicTyreRadius, ElectricMotorData electricMotorData, ElectricMotorData emDataLimited) - { - var emFld = electricMotorData.EfficiencyData.VoltageLevels.First().FullLoadCurve; - return DeclarationData.Gearbox.ComputeElectricMotorShiftPolygon(i, - emDataLimited.EfficiencyData.VoltageLevels.First().FullLoadCurve, electricMotorData.RatioADC, - gearboxGears, axlegearRatio, dynamicTyreRadius, - _shiftStrategyParameters.PEV_DeRatedDownshiftSpeedFactor * emFld.RatedSpeed, - _shiftStrategyParameters.PEV_DownshiftMinSpeedFactor * emFld.RatedSpeed); - } + { + if (!electricMotorData.EfficiencyData.MaxSpeed.IsEqual(emDataLimited.EfficiencyData.MaxSpeed)) { + throw new VectoException("Limited em data should have the same max speed as the original data"); + } + return DeclarationData.Gearbox.ComputeElectricMotorShiftPolygon( + i, + emDataLimited, + gearboxGears, + _shiftStrategyParameters.PEV_DeRatedDownshiftSpeedFactor.LimitTo(0, 1), + _shiftStrategyParameters.PEV_DownshiftMinSpeedFactor); + + // return DeclarationData.Gearbox.ComputeElectricMotorShiftPolygon(i, + // emDataLimited.EfficiencyData.VoltageLevels.First().FullLoadCurve, electricMotorData.RatioADC, + // gearboxGears, axlegearRatio, dynamicTyreRadius, + // _shiftStrategyParameters.PEV_DeRatedDownshiftSpeedFactor, + // _shiftStrategyParameters.PEV_DownshiftMinSpeedFactor); + } } } \ No newline at end of file diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Vehicle.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Vehicle.cs index 70ef9e9025..c98e1fc2f8 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Vehicle.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Vehicle.cs @@ -129,7 +129,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl var pos = positions.First(); if (pos.IsBatteryElectric()) { - var maxEMSpeed = DataBus.ElectricMotorInfo(pos).MaxSpeed; + var maxEMSpeed = DataBus.ElectricMotorInfo(pos).MaxSpeedDt; var ratio = 1.0; if (pos == PowertrainPosition.BatteryElectricE3) { @@ -142,7 +142,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl (DataBus.AngledriveInfo?.Ratio ?? 1.0); maxEMSpeed = VectoMath.Min( - DataBus.ElectricMotorInfo(pos).MaxSpeed, + DataBus.ElectricMotorInfo(pos).MaxSpeedDt, DataBus.GearboxInfo.GetGearData(DataBus.GearboxInfo.NumGears).MaxSpeed); } MaxVehicleSpeed = maxEMSpeed / ratio * DataBus.WheelsInfo.DynamicTyreRadius * 0.995; -- GitLab From 10fa9c00cddeb1b5e533c52210b17419e2ed3db8 Mon Sep 17 00:00:00 2001 From: "VKMTHD\\haraldmartini" <martini@ivt.tugraz.at> Date: Tue, 18 Mar 2025 11:55:18 +0100 Subject: [PATCH 19/22] Renamed IGearboxType to ITypedGearbox --- .../Models/SimulationComponent/IGearbox.cs | 14 +++++++------- .../SimulationComponent/Impl/CycleGearbox.cs | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/VectoCore/VectoCore/Models/SimulationComponent/IGearbox.cs b/VectoCore/VectoCore/Models/SimulationComponent/IGearbox.cs index b422e53999..2e41ad204d 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/IGearbox.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/IGearbox.cs @@ -43,16 +43,16 @@ namespace TUGraz.VectoCore.Models.SimulationComponent /// </summary> public interface IGearbox : IPowerTrainComponent, IGearboxInfo, IGearboxControl, IUpdateable { } - public interface IGearboxType : IGearbox {} + public interface ITypedGearbox : IGearbox {} - public interface IMTGearbox : IGearboxType {} + public interface IMTGearbox : ITypedGearbox {} - public interface IAMTGearbox : IGearboxType + public interface IAMTGearbox : ITypedGearbox { GearboxState GetPreviousState { get; } } - public interface IAPTGearbox : IGearboxType + public interface IAPTGearbox : ITypedGearbox { ATGearboxState GetPreviousState { get; } bool ShiftToLocked { get; } @@ -61,11 +61,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent PerSecond outAngularVelocity); } - public interface IAPTNGearbox : IGearboxType { } + public interface IAPTNGearbox : ITypedGearbox { } - public interface IPEVGearbox : IGearboxType { } + public interface IPEVGearbox : ITypedGearbox { } - public interface IIEPCGearbox : IGearboxType { } + public interface IIEPCGearbox : ITypedGearbox { } public interface ITorqueConverter : ITorqueConverterInfo, ITorqueConverterControl, IUpdateable { } } \ No newline at end of file diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/CycleGearbox.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/CycleGearbox.cs index 226212530a..81bd7362a1 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/CycleGearbox.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/CycleGearbox.cs @@ -51,7 +51,7 @@ using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { - public class CycleGearbox : AbstractGearbox<CycleGearbox.CycleGearboxState>, IGearboxType + public class CycleGearbox : AbstractGearbox<CycleGearbox.CycleGearboxState>, ITypedGearbox { /// <summary> /// True if gearbox is disengaged (no gear is set). -- GitLab From 083e77248038756c4b0b10be5411d97c4efeb00d Mon Sep 17 00:00:00 2001 From: "VKMTHD\\haraldmartini" <martini@ivt.tugraz.at> Date: Tue, 18 Mar 2025 13:32:12 +0100 Subject: [PATCH 20/22] Use IAPTGearbox in ATShiftStrategyOptimized.cs --- .../Models/SimulationComponent/IGearbox.cs | 10 +++ .../Impl/AbstractGearbox.cs | 2 +- .../Impl/Gearbox/APTGearbox.cs | 24 ++++++- .../ATShiftStrategyOptimized.cs | 64 +++++++++++-------- 4 files changed, 68 insertions(+), 32 deletions(-) diff --git a/VectoCore/VectoCore/Models/SimulationComponent/IGearbox.cs b/VectoCore/VectoCore/Models/SimulationComponent/IGearbox.cs index 2e41ad204d..81aa795e99 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/IGearbox.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/IGearbox.cs @@ -57,8 +57,18 @@ namespace TUGraz.VectoCore.Models.SimulationComponent ATGearboxState GetPreviousState { get; } bool ShiftToLocked { get; } IIdleController IdleController { set; } + bool TorqueConverterLocked { get; } + + + ResponseDryRun Initialize(GearshiftPosition gear, NewtonMeter outTorque, PerSecond outAngularVelocity); + + new bool Disengaged { get; set; } + KilogramSquareMeter EngineInertia { get; } + TorqueConverter TorqueConverter { get; } + + WattSecond ComputeShiftLosses(NewtonMeter outTorque, PerSecond outAngularVelocity, GearshiftPosition nextGearPos); } public interface IAPTNGearbox : ITypedGearbox { } diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/AbstractGearbox.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/AbstractGearbox.cs index fa9c458ef3..962f08e873 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/AbstractGearbox.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/AbstractGearbox.cs @@ -152,7 +152,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return nextGear.TorqueConverterLocked.HasValue && nextGear.TorqueConverterLocked.Value; } - protected internal WattSecond ComputeShiftLosses(NewtonMeter outTorque, PerSecond outAngularVelocity, GearshiftPosition gear) + public WattSecond ComputeShiftLosses(NewtonMeter outTorque, PerSecond outAngularVelocity, GearshiftPosition gear) { var ratio = ModelData.Gears[gear.Gear].Ratio; if (double.IsNaN(ratio)) { diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Gearbox/APTGearbox.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Gearbox/APTGearbox.cs index c5e91915bb..47c608f540 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Gearbox/APTGearbox.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Gearbox/APTGearbox.cs @@ -51,17 +51,33 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Gearbox public class APTGearbox : AbstractGearbox<ATGearboxState>, IHybridControlledGearbox, IAPTGearbox { protected internal readonly IShiftStrategy _strategy; - protected internal readonly TorqueConverter TorqueConverter; + private IIdleController _idleController; internal WattSecond _powershiftLossEnergy; - protected internal KilogramSquareMeter EngineInertia; public bool TorqueConverterLocked => CurrentState.Gear.TorqueConverterLocked.Value; //set { CurrentState.TorqueConverterLocked = value; } public override bool TCLocked => Gear.TorqueConverterLocked.Value; + public TorqueConverter TorqueConverter + { + get; + private set; + } + + // public WattSecond ComputeShiftLosses(NewtonMeter outTorque, PerSecond outAngularVelocity, GearshiftPosition nextGearPos) + // { + // return base.ComputeShiftLosses(outTorque, outAngularVelocity, nextGearPos); + // } + + public KilogramSquareMeter EngineInertia + { + get; + private set; + } + public APTGearbox(IVehicleContainer container, IShiftStrategy strategy) : this(container, strategy, false) { @@ -607,7 +623,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Gearbox public ATGearboxState GetPreviousState => PreviousState.Clone(); - #endregion + + + #endregion } public class ATGearboxState : GearboxState diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Shiftstrategies/ATShiftStrategyOptimized.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Shiftstrategies/ATShiftStrategyOptimized.cs index 1c28784d5c..59737053e1 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Shiftstrategies/ATShiftStrategyOptimized.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Shiftstrategies/ATShiftStrategyOptimized.cs @@ -648,15 +648,23 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies if (shiftTimeReached && Container.DriverInfo.DrivingAction == DrivingAction.Accelerate) { if (Container.VehicleInfo.VehicleSpeed < Container.DrivingCycleInfo.CycleData.LeftSample.VehicleTargetSpeed - 10.KMPHtoMeterPerSecond() && Container.DriverInfo.DriverAcceleration < 0.SI<MeterPerSquareSecond>()) { - var tmpResponseCurr = (ResponseDryRun)_gearbox.Request(absTime, dt, outTorque, outAngularVelocity, true); + var currentGear = gear; + var tmpResponseCurr = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, gear); + + // var tmpResponseCurr = (ResponseDryRun)_gearbox.Request(absTime, dt, outTorque, outAngularVelocity, true); if (_gearbox.Gear > Gears.First()) { + // var tmpGear = + // clone current state of _nextgear, set gearbox state to lower gear, issue request, restore old gearbox state - var tmp = _nextGear.Clone(); - var gbxState = new NextGearState(absTime, _gearbox); - tmp.Gear = Gears.Predecessor(_gearbox.Gear); - SetGear(tmp); - var tmpResponseDs = (ResponseDryRun)_gearbox.Request(absTime, dt, outTorque, outAngularVelocity, true); - SetGear(gbxState); + // var tmp = _nextGear.Clone(); + // var gbxState = new NextGearState(absTime, _gearbox); + // tmp.Gear = Gears.Predecessor(_gearbox.Gear); + // SetGear(tmp); + // var tmpResponseDs = (ResponseDryRun)_gearbox.Request(absTime, dt, outTorque, outAngularVelocity, true); + // SetGear(gbxState); + var tmpGear = Gears.Predecessor(currentGear); + var tmpResponseDs = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, tmpGear); + // done if (tmpResponseDs.Engine.EngineSpeed.IsSmaller(Container.EngineInfo.EngineN95hSpeed) && tmpResponseDs.DeltaFullLoad - Formulas.InertiaPower( tmpResponseDs.Engine.EngineSpeed, Container.EngineInfo.EngineSpeed, EngineInertia, dt) < tmpResponseCurr.DeltaFullLoad) { @@ -773,12 +781,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies _nextGear.SetState(absTime, false, Gears.Predecessor(gear)); } - protected virtual void SetGear(NextGearState gbxState) - { - _gearbox.Gear = gbxState.Gear; - //_gearbox.TorqueConverterLocked = gbxState.TorqueConverterLocked; - _gearbox.Disengaged = gbxState.Disengaged; - } + // protected virtual void SetGear(NextGearState gbxState) + // { + // _gearbox.Gear = gbxState.Gear; + // //_gearbox.TorqueConverterLocked = gbxState.TorqueConverterLocked; + // _gearbox.Disengaged = gbxState.Disengaged; + // } private double GetFCRating(PerSecond engineSpeed, NewtonMeter tqCurrent) { @@ -899,10 +907,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies Gear = nextGearState.Gear; } - public NextGearState(Second absTime, APTGearbox gearbox) - { - SetState(absTime, gearbox); - } + // public NextGearState(Second absTime, IAPTGearbox gearbox) + // { + // SetState(absTime, gearbox); + // } public void SetState(Second absTime, bool disengaged, GearshiftPosition gear) { @@ -911,17 +919,17 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies Gear = gear; } - public void SetState(Second absTime, APTGearbox gearbox) - { - AbsTime = absTime; - Disengaged = gearbox.Disengaged; - Gear = gearbox.Gear; - } - - public NextGearState Clone() - { - return new NextGearState(this); - } + // public void SetState(Second absTime, IAPTGearbox gearbox) + // { + // AbsTime = absTime; + // Disengaged = gearbox.Disengaged; + // Gear = gearbox.Gear; + // } + // + // public NextGearState Clone() + // { + // return new NextGearState(this); + // } } } } -- GitLab From d946af37b59c6ee236f3325693ea2e11155e6dc8 Mon Sep 17 00:00:00 2001 From: "VKMTHD\\haraldmartini" <martini@ivt.tugraz.at> Date: Tue, 18 Mar 2025 14:13:22 +0100 Subject: [PATCH 21/22] Added APTN ShiftStrategyTests --- .../APTNShiftStrategyTests.cs | 2004 +++++++++++++++++ 1 file changed, 2004 insertions(+) create mode 100644 Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/APTNShiftStrategyTests.cs diff --git a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/APTNShiftStrategyTests.cs b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/APTNShiftStrategyTests.cs new file mode 100644 index 0000000000..69476d7097 --- /dev/null +++ b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/APTNShiftStrategyTests.cs @@ -0,0 +1,2004 @@ +using Moq; +using NUnit.Framework; +using TUGraz.VectoCommon.InputData; +using TUGraz.VectoCommon.Models; +using TUGraz.VectoCommon.Utils; +using TUGraz.VectoCore.InputData.Impl; +using TUGraz.VectoCore.InputData.Reader.ComponentData; +using TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.SimulationComponents; +using TUGraz.VectoCore.Models.Connector.Ports.Impl; +using TUGraz.VectoCore.Models.Declaration; +using TUGraz.VectoCore.Models.Simulation; +using TUGraz.VectoCore.Models.Simulation.Data; +using TUGraz.VectoCore.Models.Simulation.DataBus; +using TUGraz.VectoCore.Models.Simulation.Impl; +using TUGraz.VectoCore.Models.SimulationComponent; +using TUGraz.VectoCore.Models.SimulationComponent.Data; +using TUGraz.VectoCore.Models.SimulationComponent.Data.ElectricMotor; +using TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox; +using TUGraz.VectoCore.Models.SimulationComponent.Impl; +using TUGraz.VectoCore.Models.SimulationComponent.Impl.Gearbox; +using TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies; +using TUGraz.VectoCore.Models.SimulationComponent.Strategies; +using TUGraz.VectoCore.Tests.Utils; +using TUGraz.VectoCore.Utils; +using Range = System.Range; + +namespace TUGraz.Vecto.UnitTests.TestCases.Components.GearShiftStrategy +{ + [TestFixture] + public class APTNShiftStrategyTests + { + [TestCase(500, 80, 1)] + [TestCase(5, 500, 2)] + public void InitGear(double torque_Nm, double speed_rpm, int expectedGear) + { + // the first element 0.0 is just a placeholder for axlegear, not used in this test + var ratios = new[] { 0.0, 3.86, 1.93 }; + + var container = GetMocks(ratios); + + var shiftStrategy = GetShiftStrategyAndGearbox(container, out var gearbox); + + var absTime = 0.SI<Second>(); + var dt = 0.5.SI<Second>(); + + var torque = torque_Nm.SI<NewtonMeter>(); + var speed = speed_rpm.RPMtoRad(); + + var result = shiftStrategy.InitGear(absTime, dt, torque, speed); + + var newGear = result.Gear; + Assert.AreEqual(expectedGear, newGear); + + + + } + + [TestCase(5000, 80, 1)] + [TestCase(5, 500, 2)] + public void InitStartGear(double torque_Nm, double speed_rpm, int expectedGear) + { + // the first element 0.0 is just a placeholder for axlegear, not used in this test + var ratios = new[] { 0.0, 3.86, 1.93 }; + + var container = GetMocks(ratios); + container.Setup(c => c.VehicleInfo.VehicleSpeed).Returns(0.KMPHtoMeterPerSecond()); + + var shiftStrategy = GetShiftStrategyAndGearbox(container, out var gearbox); + + var absTime = 0.SI<Second>(); + var dt = 0.5.SI<Second>(); + + var torque = torque_Nm.SI<NewtonMeter>(); + var speed = speed_rpm.RPMtoRad(); + + var result = shiftStrategy.InitGear(absTime, dt, torque, speed); + + var newGear = result.Gear; + Assert.AreEqual(expectedGear, newGear); + + + + } + + [TestCase( + 500, + 80, + 500, + 10000, + 1, + 2, TestName = "Emergency UpShift")] + + [TestCase( + 500, + 80, + 1000, + 1800, + 1, + 2, TestName = "UpShift")] + [TestCase( + 500, + 80, + 1000, + 800, + 1, + 1, TestName = "No Upshift")] + public void Upshift(double init_outTorque_Nm, double init_outSpeed_rpm, double outTorque_Nm, + double outSpeed_rpm, int currentGear, int expectedGear) + { + CheckUpshift(init_outTorque_Nm, init_outSpeed_rpm, outTorque_Nm, outSpeed_rpm, currentGear, expectedGear, false); + } + + + public void CheckUpshift(double init_outTorque_Nm, double init_outSpeed_rpm, double outTorque_Nm, + double outSpeed_rpm, int currentGear, int expectedGear, bool effShift) + { + // the first element 0.0 is just a placeholder for axlegear, not used in this test + var ratios = new[] { 0.0, 3.86, 1.93 }; + var ratio = ratios[currentGear]; + var container = GetMocks(ratios); + + if (!effShift) { + DisableEffshift(container.Object.RunData); + } + + + var shiftRequired = currentGear != expectedGear; + + var shiftStrategy = GetShiftStrategyAndGearbox(container, out var gearbox); + // var gear = new GearshiftPosition((uint)currentGear); + // gearbox.Gear = gear; + + var absTime = 0.SI<Second>(); + var dt = 0.5.SI<Second>(); + + var init_outTorque = init_outTorque_Nm.SI<NewtonMeter>(); + var init_outAngularVelocity = init_outSpeed_rpm.RPMtoRad(); + + + var outTorque = outTorque_Nm.SI<NewtonMeter>(); + var outAngularVelocity = outSpeed_rpm.RPMtoRad(); + + var inTorque = outTorque / ratio; + var inAngularVelocity = outAngularVelocity * ratio; + + var lastShiftTime = float.MinValue.SI<Second>(); + + var response = new ResponseSuccess(this); + + Console.WriteLine( + $"OutTorque: {outTorque}\n" + + $"InTorque: {inTorque} \n" + + $"OutSpeed: {outAngularVelocity.AsRPM} [rpm]\n" + + $"InSpeed: {inAngularVelocity.AsRPM} [rpm]\n"); + + + //Init gear + var initResult = shiftStrategy.InitGear(absTime, dt, init_outTorque, init_outAngularVelocity); + Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(currentGear)); + + //Check shift required + var result = shiftStrategy.ShiftRequired(absTime, dt, + outTorque: outTorque, + outAngularVelocity: outAngularVelocity, + inTorque: inTorque, + inAngularVelocity: inAngularVelocity, + gear: shiftStrategy.NextGear, + lastShiftTime: lastShiftTime, + response: response); + + Assert.AreEqual(shiftRequired, result); + Assert.AreEqual(expectedGear, shiftStrategy.NextGear.Gear); + + + + } + + [TestCase( + 500, + 80, + -10, + 1000, + 1, + 2, TestName = "UpShift")] + public void EarlyUpshift(double init_outTorque_Nm, double init_outSpeed_rpm, double outTorque_Nm, + double outSpeed_rpm, int currentGear, int expectedGear) + { + // the first element 0.0 is just a placeholder for axlegear, not used in this test + var ratios = new[] { 0.0, 3.86, 1.93 }; + var ratio = ratios[currentGear]; + var container = GetMocks(ratios); + container.Setup(c => c.VehicleInfo.VehicleSpeed).Returns(20.KMPHtoMeterPerSecond()); + + + var shiftRequired = currentGear != expectedGear; + + var shiftStrategy = GetShiftStrategyAndGearbox(container, out var gearbox); + var gear = new GearshiftPosition((uint)currentGear); + // gearbox.Gear = gear; + + var absTime = 0.SI<Second>(); + var dt = 0.5.SI<Second>(); + + var init_outTorque = init_outTorque_Nm.SI<NewtonMeter>(); + var init_outAngularVelocity = init_outSpeed_rpm.RPMtoRad(); + + + var outTorque = outTorque_Nm.SI<NewtonMeter>(); + var outAngularVelocity = outSpeed_rpm.RPMtoRad(); + + var inTorque = outTorque / ratio; + var inAngularVelocity = outAngularVelocity * ratio; + + var lastShiftTime = float.MinValue.SI<Second>(); + + var response = new ResponseSuccess(this); + + Console.WriteLine( + $"OutTorque: {outTorque}\n" + + $"InTorque: {inTorque} \n" + + $"OutSpeed: {outAngularVelocity.AsRPM} [rpm]\n" + + $"InSpeed: {inAngularVelocity.AsRPM} [rpm]\n"); + + + //Init gear + var initResult = shiftStrategy.InitGear(absTime, dt, init_outTorque, init_outAngularVelocity); + Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(currentGear)); + + //Check shift required + var result = shiftStrategy.ShiftRequired(absTime, dt, + outTorque: outTorque, + outAngularVelocity: outAngularVelocity, + inTorque: inTorque, + inAngularVelocity: inAngularVelocity, + gear: shiftStrategy.NextGear, + lastShiftTime: lastShiftTime, + response: response); + + Assert.AreEqual(shiftRequired, result); + Assert.AreEqual(expectedGear, shiftStrategy.NextGear.Gear); + + + } + + [TestCase( + 5, + 200, + 2000, + 200, + 2, + 1, TestName = "Downshift")] + public void Downshift(double init_outTorque_Nm, double init_outSpeed_rpm, double outTorque_Nm, + double outSpeed_rpm, int currentGear, int expectedGear, int speedKmh=1) + { + var ratios = new[] { 0.0, 3.86, 1.93 }; + CheckDownshift(init_outTorque_Nm, init_outSpeed_rpm, outTorque_Nm, outSpeed_rpm, currentGear, expectedGear, ratios, false, speedKmh); + } + + [TestCase( + 5, + 200, + -500, + 200, + 4, + 2, + 40, TestName = "EarlyDownshift")] + public void EarlyDownshift(double init_outTorque_Nm, double init_outSpeed_rpm, double outTorque_Nm, + double outSpeed_rpm, int currentGear, int expectedGear, int speedKmh=1) + { + var ratios = new[] { 0.0, 3.86, 3, 2.5, 1.93 }; + CheckDownshift(init_outTorque_Nm, init_outSpeed_rpm, outTorque_Nm, outSpeed_rpm, currentGear, expectedGear, ratios, true, speedKmh); + } + + [TestCase( + 5, + 200, + 2000, + 40, + 4, + 2, TestName = "Downshift_SkipGear")] + public void DownshiftSkipGears(double init_outTorque_Nm, double init_outSpeed_rpm, double outTorque_Nm, + double outSpeed_rpm, int currentGear, int expectedGear) + { + var ratios = new[] { 0.0, 3.86, 3, 2.5, 1.93 }; + CheckDownshift(init_outTorque_Nm, init_outSpeed_rpm, outTorque_Nm, outSpeed_rpm, currentGear, expectedGear, ratios, false); + } + + private void DisableEffshift(VectoRunData runData) + { + TestContext.WriteLine("EffShift Disabled"); + runData.GearshiftParameters.AllowedGearRangeFC = 0; + } + + private void DisableEffshift(Mock<IVehicleContainer> vehicleContainer) + { + DisableEffshift(vehicleContainer.Object.RunData); + } + + public void CheckDownshift( + double init_outTorque_Nm, + double init_outSpeed_rpm, + double outTorque_Nm, + double outSpeed_rpm, + int currentGear, + int expectedGear, + double[] ratios, + bool effShift = true, + int vehicleSpeed_kmH = 1) + { + // the first element 0.0 is just a placeholder for axlegear, not used in this test + var ratio = ratios[currentGear]; + var container = GetMocks(ratios); + container.Setup(c => c.VehicleInfo.VehicleSpeed).Returns(vehicleSpeed_kmH.KMPHtoMeterPerSecond()); + + + if (!effShift) { + DisableEffshift(container.Object.RunData); + } + + var shiftRequired = currentGear != expectedGear; + + var shiftStrategy = GetShiftStrategyAndGearbox(container, out var gearbox); + var gear = new GearshiftPosition((uint)currentGear); + // gearbox.Gear = gear; + + var absTime = 0.SI<Second>(); + var dt = 0.5.SI<Second>(); + + var init_outTorque = init_outTorque_Nm.SI<NewtonMeter>(); + var init_outAngularVelocity = init_outSpeed_rpm.RPMtoRad(); + + var outTorque = outTorque_Nm.SI<NewtonMeter>(); + var outAngularVelocity = outSpeed_rpm.RPMtoRad(); + + var inTorque = outTorque / ratio; + var inAngularVelocity = outAngularVelocity * ratio; + + var lastShiftTime = float.MinValue.SI<Second>(); + + + + Console.WriteLine( + $"OutTorque: {outTorque}\n" + + $"InTorque: {inTorque} \n" + + $"OutSpeed: {outAngularVelocity}\n" + + $"InSpeed: {inAngularVelocity}\n"); + + + //Init gear + var initResult = shiftStrategy.InitGear(absTime, dt, init_outTorque, init_outAngularVelocity); + Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(currentGear)); + + var response = new ResponseSuccess(this) { }; + response.ElectricMotor.AngularVelocity = inAngularVelocity; + response.ElectricMotor.TorqueRequestEmMap = inTorque; + response.ElectricMotor.DeRatingActive = false; + // response.ElectricMotor; + + //Check shift required + var result = shiftStrategy.ShiftRequired(absTime, dt, + outTorque: outTorque, + outAngularVelocity: outAngularVelocity, + inTorque: inTorque, + inAngularVelocity: inAngularVelocity, + gear: shiftStrategy.NextGear, + lastShiftTime: lastShiftTime, + response: response); + + Assert.AreEqual(shiftRequired, result, "Expected Shift"); + Assert.AreEqual(expectedGear, shiftStrategy.NextGear.Gear); + + + + } + + + + + + private PEVAMTShiftStrategy GetShiftStrategyAndGearbox(Mock<IVehicleContainer> container, out IEPCGearbox gearbox) + { + var shiftStrategy = new APTNShiftStrategy(container.Object); + + var gbxFactory = new Mock<IIEPCGearboxFactory>(); + gbxFactory.Setup(g => g.CreateIEPCGearbox( + false, + It.IsAny<IVehicleContainer>(), + It.IsAny<IShiftStrategy>())).Returns( + (bool singleSpeed, IVehicleContainer container, IShiftStrategy shiftStrategy) => { + return new IEPCGearboxMultipleGears(container, shiftStrategy); + }); + + gearbox = new IEPCGearbox(container.Object, + shiftStrategy, gbxFactory.Object); + + SetVelocityDropLookupData(shiftStrategy); + + container.Setup(c => c.GearboxInfo).Returns(gearbox); + + + return shiftStrategy; + } + + private Mock<IVehicleContainer> GetMocks(double[] ratios) + { + var container = new Mock<IVehicleContainer>(); + + //RunData + var runData = GetRunData(ratios); + container.Setup(r => r.RunData).Returns(runData); + + //EmInfo + var em = GetElectricMotor(container.Object, runData.ElectricMachinesData.Single().Item2); + container.Setup(c => c.ElectricMotorInfo(PowertrainPosition.BatteryElectricE2)) + .Returns(em); + container.Setup(c => c.PowertrainInfo.ElectricMotorPositions).Returns(new[] { + PowertrainPosition.BatteryElectricE2 + }); + + // container.Setup(r => r.GetElectricMotors()).Returns(new List<IElectricMotorInfo>(){em}); + + container.Setup(c => c.PowertrainInfo.HasCombustionEngine).Returns(false); + + //BatteryInfo + container.Setup(c => c.BatteryInfo.InternalVoltage).Returns(700.SI<Volt>()); + + //VehicleInfo + container.Setup(c => c.VehicleInfo.VehicleSpeed).Returns(1.KMPHtoMeterPerSecond()); + container.Setup(c => c.VehicleInfo.VehicleStopped).Returns(false); + + //DriverInfo + container.Setup(c => c.DriverInfo.DriverBehavior).Returns(DrivingBehavior.Accelerating); + container.Setup(c => c.DriverInfo.DrivingAction).Returns(DrivingAction.Accelerate); + // container.Set + + //PowertrainBuilder, SimplePowertrain + var testPt = GetTestPowertrain(ratios, container, out _); + var ptBuilder = new Mock<ISimplePowertrainBuilder>(); + ptBuilder.Setup(c => c.CreateTestPowertrain( + It.IsAny<IVehicleContainer>(), It.IsAny<bool>())) + .Returns(testPt.Object); + ptBuilder.Setup(c => c.CreateTestPowertrain( + It.IsAny<IVehicleContainer>(), It.IsAny<bool>(), It.IsAny<VectoSimulationJobType>())) + .Returns(testPt.Object); + container.Setup(c => c.SimplePowertrainBuilder).Returns(ptBuilder.Object); + + //DrivingCycleInfo + container.Setup(c => c.DrivingCycleInfo.RoadGradient).Returns(0.SI<Radian>()); + + return container; + } + + private ElectricMotor GetElectricMotor(IVehicleContainer container, ElectricMotorData emData) + { + var emControl = new SimpleElectricMotorControl(); + + var electricMotor = new ElectricMotor(container: container, emData, emControl, + PowertrainPosition.BatteryElectricE2); + + //Connect Electric System + var es = GetMockElectricSystem(); + electricMotor.Connect(es.Object); + return electricMotor; + } + + private TestPowertrainElectricMotor GetTestPowertrainElectricMotor(ISimpleVehicleContainer container, + ElectricMotorData emData) + { + var emControl = new SimpleElectricMotorControl(); + + var electricMotor = new TestPowertrainElectricMotor(container: container, emData, emControl, + PowertrainPosition.BatteryElectricE2); + + //Connect Electric System + var es = GetMockElectricSystem(); + electricMotor.Connect(es.Object); + return electricMotor; + } + + private Mock<ITestPowertrain> GetTestPowertrain(double[] ratios, + Mock<IVehicleContainer> container, + out Mock<ISimpleVehicleContainer> simplePt) + { + var testPt = new Mock<ITestPowertrain>(); + simplePt = GetSimplePowertrain(ratios, container, out var gbx); + var simplePtObj = simplePt.Object; + testPt.Setup(t => t.ElectricMotors).Returns(() => { + var dict = new Dictionary<PowertrainPosition, ITestpowertrainElectricMotor>(); + foreach (var (k, v) in simplePtObj.ElectricMotors) { + if (v is ITestpowertrainElectricMotor testEm) { + dict[k] = testEm; + } else { + throw new Exception("Expected TestElectricMotor in simple powertrain"); + } + } + return dict; + }); + + testPt.Setup(t => t.Container).Returns(simplePt.Object); + + testPt.Setup(t => t.Gearbox).Returns(gbx.Object); + return testPt; + } + + private Mock<IElectricSystem> GetMockElectricSystem() + { + var electricSystem = new Mock<IElectricSystem>(); + + + electricSystem + .Setup(es => es.Request(It.IsAny<Second>(), It.IsAny<Second>(), It.IsAny<Watt>(), true)) + .Returns((Second t, Second dt, Watt powerDemand, bool dryrun) => { + + var response = new Mock<IElectricSystemResponse>(); + response + .Setup(mr => mr.MaxPowerDrive) + .Returns(-100E3.SI<Watt>()); + response + .Setup(mr => mr.MaxPowerDrag) + .Returns(100E3.SI<Watt>()); + response + .Setup(mr => mr.RESSPowerDemand).Returns(powerDemand); + + + + + return response.Object; + }); + + + return electricSystem; + } + + private ElectricMotor GetMockElectricMotor(IVehicleContainer container, ElectricMotorData emData) + { + var emControl = new SimpleElectricMotorControl(); + + var electricMotor = new ElectricMotor(container: container, emData, emControl, + PowertrainPosition.BatteryElectricE2); + + //Connect Electric System + var es = GetMockElectricSystem(); + electricMotor.Connect(es.Object); + return electricMotor; + } + + private Mock<ISimpleVehicleContainer> GetSimplePowertrain( + double[] ratios, + Mock<IVehicleContainer> container, + out Mock<ITestPowertrainTransmission> testGbx) + { + var simplePt = new Mock<ISimpleVehicleContainer>(); + simplePt.Setup(s => s.IsTestPowertrain).Returns(true); + + + var components = new List<VectoSimulationComponent>(); + + var runData = container.Object.RunData; + var em = GetTestPowertrainElectricMotor(simplePt.Object, runData.ElectricMachinesData.Single().Item2); + var emDict = new Dictionary<PowertrainPosition, IElectricMotorInfo>() { + { PowertrainPosition.BatteryElectricE2, em }, + }; + simplePt.Setup(r => r.ElectricMotorInfo(PowertrainPosition.BatteryElectricE2)) + .Returns(em); + + //BatteryInfo + simplePt.Setup(s => s.BatteryInfo.InternalVoltage).Returns(700.SI<Volt>()); + + simplePt.Setup(s => s.ElectricMotors).Returns(emDict); + + simplePt.Setup(s => s.PowertrainInfo.HasCombustionEngine).Returns(false); + + simplePt.Setup(s => s.RunData).Returns(runData); + + testGbx = GetTestGearbox(simplePt.Object, em, runData.GearboxData.Gears); + + simplePt.Setup(s => s.GearboxCtl).Returns(testGbx.Object); + simplePt.Setup(s => s.GearboxInfo).Returns(testGbx.Object); + simplePt.Setup(s => s.GearboxOutPort).Returns(testGbx.Object); + + simplePt.Setup(s => s.SimulationComponents()).Returns(components); + simplePt.Setup(s => s.Brakes).Returns(new Mock<IBrakes>().Object); + + //Take from real powertrain + simplePt.Setup(s => s.VehicleInfo).Returns(container.Object.VehicleInfo); + simplePt.Setup(s => s.DriverInfo).Returns(container.Object.DriverInfo); + + return simplePt; + } + + Mock<ITestPowertrainTransmission> GetTestGearbox( + ISimpleVehicleContainer simpleContainer, + TestPowertrainElectricMotor em, + Dictionary<uint, GearData> ratios) + { + Mock<IAMTGearbox> amtGearbox = new Mock<IAMTGearbox>(); + amtGearbox.Name = "PEVAMT_TestGearbox"; + Mock<ITestPowertrainTransmission> gbx = amtGearbox.As<ITestPowertrainTransmission>(); + + gbx.Setup(g => g.LastUpshift).Returns(-double.MaxValue.SI<Second>()); + gbx.Setup(g => g.LastDownshift).Returns(-double.MaxValue.SI<Second>()); + + GearshiftPosition gear = null; + gbx.SetupGet(g => g.Gear).Returns(() => gear); + gbx.SetupSet(g => g.SetGear = It.IsAny<GearshiftPosition>()) + .Callback<GearshiftPosition>(p => { + gear = p; + }); + + + GearshiftPosition nextGear = null; + gbx.SetupGet(g => g.NextGear).Returns(() => nextGear); + gbx.SetupSet(g => g.SetNextGear = It.IsAny<GearshiftPosition>()) + .Callback<GearshiftPosition>(p => nextGear = p); + + + gbx.Setup(p => p.Initialize(It.IsAny<NewtonMeter>(), + It.IsAny<PerSecond>())).Returns((NewtonMeter outTorque, PerSecond outSpeed) => { + var ratio = + gbx.Object.Gear == null ? 1.0 : ratios[gbx.Object.Gear.Gear].Ratio; + + var inSpeed = outSpeed * ratio; + var inTorque = outTorque / ratio; + + em.Initialize(inTorque, inSpeed); + return new ResponseSuccess(this) + { + + }; + }); + gbx.Setup(p => p.Request( + It.IsAny<Second>(), + It.IsAny<Second>(), + It.IsAny<NewtonMeter>(), + It.IsAny<PerSecond>(), + true)).Returns(( + Second absTime, + Second dt, + NewtonMeter outTorque, + PerSecond outSpeed, + bool dryRun) => { + + var ratio = + gbx.Object.Gear == null ? 1.0 : ratios[gbx.Object.Gear.Gear].Ratio; + + var inSpeed = outSpeed * ratio; + var inTorque = outTorque / ratio; + + var emResponse = em.Request(absTime, dt, inTorque, inSpeed, dryRun); + return dryRun + ? new ResponseDryRun(this, emResponse) { + // Engine = { + // PowerRequest = n * t, EngineSpeed = n * ratio, + // DynamicFullLoadPower = (t / ratio + 2300.SI<NewtonMeter>()) * n * ratio, + // TotalTorqueDemand = t, + // }, + // ElectricMotor = emResponse.ElectricMotor, + Gearbox = { + Gear = gbx.Object.Gear, + InputSpeed = inSpeed, + InputTorque = inTorque, + OutputSpeed = outSpeed, + OutputTorque = outTorque, + PowerRequest = outSpeed * outTorque, + }, + Clutch = { PowerRequest = outSpeed * outTorque }, + DeltaFullLoad = outSpeed * outTorque / 2 * (-1) + } + : new ResponseSuccess(this) { + Gearbox = { + Gear = gbx.Object.Gear, + InputSpeed = inSpeed, + InputTorque = inTorque, + }, + Clutch = { PowerRequest = outSpeed * outTorque } + }; + }); + return gbx; + } + + + private VectoRunData GetRunData(double[] ratios) + { + var runData = new VectoRunData(); + + //GearShiftParameters + var gearshiftParameters = new ShiftStrategyParameters() { + TorqueReserve = 0.0, + TimeBetweenGearshifts = 2.SI<Second>(), + DownshiftAfterUpshiftDelay = 2.SI<Second>(), + UpshiftAfterDownshiftDelay = 2.SI<Second>(), + UpshiftMinAcceleration = 0.1.SI<MeterPerSquareSecond>(), + StartSpeed = 0.KMPHtoMeterPerSecond(), + RatingFactorCurrentGear = 1, + AllowedGearRangeFC = 2, + MinEngineSpeedPostUpshift = 0.RPMtoRad(), + }; + runData.GearshiftParameters = gearshiftParameters; + + runData.ElectricMachinesData = GetElectricMachinesData(); + var emData = runData.ElectricMachinesData.Single(i => i.Item1 == PowertrainPosition.BatteryElectricE2) + .Item2; + //VehicleData + var vehicleData = new VehicleData() { + DynamicTyreRadius = 0.492.SI<Meter>(), + }; + runData.VehicleData = vehicleData; + + //CycleData + var mockCycle = new Mock<IDrivingCycleData>(); + mockCycle.Setup(cd => cd.Entries).Returns( + new List<DrivingCycleData.DrivingCycleEntry>() { + new DrivingCycleData.DrivingCycleEntry() { + RoadGradient = 0.SI<Radian>() + } + }); + runData.Cycle = mockCycle.Object; + + + //Gearboxdata + var gearboxInputData = new Mock<IGearboxDeclarationInputData>(); + + var gearsInputData = new List<Mock<ITransmissionInputData>>(); + + gearboxInputData.Setup( + d => d.Gears) + .Returns(gearsInputData.Select(m => m.Object) + .ToList()); + + + var gearboxData = new GearboxData() { + Gears = new Dictionary<uint, GearData>(ratios.Length), + InputData = gearboxInputData.Object, + Type = GearboxType.AMT, + TractionInterruption = 1.SI<Second>(), + Inertia = 0.SI<KilogramSquareMeter>(), + }; + + + + + + runData.GearboxData = gearboxData; + for (uint i = 1; i < ratios.Length; i++) { + gearboxData.Gears[i] = new GearData + { + Ratio = ratios[i], + LossMap = TransmissionLossMapReader.Create(0.96, ratios[i], $"Gear {i}"), + + }; + } + var axlRatio = 3.240355; + var gearsInput = gearboxData.Gears.Select(x => { + var r = new Mock<ITransmissionInputData>(); + r.Setup(g => g.Ratio).Returns(x.Value.Ratio); + r.Setup(g => g.MaxTorque).Returns(x.Value.MaxTorque); + r.Setup(g => g.MaxInputSpeed).Returns(x.Value.MaxSpeed); + + return r.Object; + }).ToList(); + foreach (var entry in gearboxData.Gears) { + var gearIdx = (int)entry.Key - 1; + var dynamicTyreRadius = 0.5.SI<Meter>(); + + var shiftPolygon = DeclarationData.Gearbox.ComputeElectricMotorShiftPolygon( + gearIdx, + emData, + gearsInput); + + entry.Value.ShiftPolygon = shiftPolygon; + + } + + + return runData; + } + + private IList<Tuple<PowertrainPosition, ElectricMotorData>> GetElectricMachinesData() + { + //Nr of electric machines + const int emCount = 2; + //ElectricMachines + // var electricMotorData = new ElectricMotorData() { + // + // }; + var emDataAdapter = new ElectricMachinesDataAdapter(); + var emInputData = new Mock<IElectricMotorDeclarationInputData>(); + + var powerMapMock = new Mock<IElectricMotorPowerMap>(); + powerMapMock.Setup(pm => pm.Gear).Returns(0); + powerMapMock.Setup(pm => pm.PowerMap).Returns(GetEfficiencyMapData()); + + var voltageLevels = new List<IElectricMotorVoltageLevel>() { + new ElectricMotorVoltageLevel(){ + VoltageLevel = 100.SI<Volt>(), + ContinuousTorque = 450.SI<NewtonMeter>(), + ContinuousTorqueSpeed = 2460.RPMtoRad(), + OverloadTorque = 485.SI<NewtonMeter>(), + OverloadTestSpeed = 2460.RPMtoRad(), + OverloadTime = 120.SI<Second>(), + FullLoadCurve = GetFullLoadCurveData(), + PowerMap = new List<IElectricMotorPowerMap>(){powerMapMock.Object} + }, + new ElectricMotorVoltageLevel(){ + VoltageLevel = 1000.SI<Volt>(), + ContinuousTorque = 450.SI<NewtonMeter>(), + ContinuousTorqueSpeed = 2460.RPMtoRad(), + OverloadTorque = 485.SI<NewtonMeter>(), + OverloadTestSpeed = 2460.RPMtoRad(), + OverloadTime = 120.SI<Second>(), + FullLoadCurve = GetFullLoadCurveData(), + PowerMap = new List<IElectricMotorPowerMap>(){powerMapMock.Object} + } + }; + + emInputData.Setup(em => em.CertificationMethod).Returns(CertificationMethod.Measured); + emInputData.Setup(em => em.Inertia).Returns(0.225.SI<KilogramSquareMeter>()); + emInputData.Setup(em => em.R85RatedPower).Returns(250E3.SI<Watt>()); + emInputData.Setup(em => em.ElectricMachineType).Returns(ElectricMachineType.ASM); + emInputData.Setup(em => em.VoltageLevels).Returns(voltageLevels); + emInputData.Setup(em => em.DragCurve).Returns(GetDragCurveData); + + var adcInputData = new Mock<IADCDeclarationInputData>(); + adcInputData.Setup(adc => adc.Ratio).Returns(1.0f); + + var emsInputData = new Mock<IElectricMachinesDeclarationInputData>(); + emsInputData.Setup(em => em.Entries).Returns( + new List<ElectricMachineEntry<IElectricMotorDeclarationInputData>>() { + new ElectricMachineEntry<IElectricMotorDeclarationInputData>() { + Count = emCount, + Position = PowertrainPosition.BatteryElectricE2, + ElectricMachine = emInputData.Object, + ADC = adcInputData.Object, + RatioADC = 2.0, + MechanicalTransmissionEfficiency = 0.97, + } + }); + + var avgVoltage = 200.SI<Volt>(); + IDictionary<PowertrainPosition, IList<Tuple<Volt, TableData>>> torqueLimits = new Dictionary<PowertrainPosition, IList<Tuple<Volt, TableData>>>(); + + var electricMachinesData = emDataAdapter.CreateElectricMachines(emsInputData.Object, torqueLimits:torqueLimits, + avgVoltage, null); + + + + + + return electricMachinesData; + + } + + private TableData GetDragCurveData() + { + return InputDataHelper.InputDataAsTableData( + "n [rpm] , T_drag [Nm]", + "0 , -6.06", + "7363.77 , -30.31"); + } + + + private TableData GetFullLoadCurveData() + { + return InputDataHelper.InputDataAsTableData("n [rpm] , T_drive [Nm] , T_drag [Nm]", + #region data + "0,485,-485", +"2461.158914,485,-485", +"2452.135493,485,-485", +"2466.863034,483.8845,-483.8845", +"2481.590574,481.010875,-481.010875", +"2496.318115,478.173625,-478.173625", +"2503.681885,476.767125,-476.767125", +"2577.319588,463.138625,-463.138625", +"2650.95729,450.274,-450.274", +"2724.594993,438.1005,-438.1005", +"2798.232695,426.58175,-426.58175", +"2871.870398,415.645,-415.645", +"2945.5081,405.253875,-405.253875", +"3019.145803,395.359875,-395.359875", +"3092.783505,385.950875,-385.950875", +"3166.421208,376.978375,-376.978375", +"3240.05891,368.406,-368.406", +"3313.696613,360.221625,-360.221625", +"3387.334315,352.388875,-352.388875", +"3460.972018,344.895625,-344.895625", +"3534.60972,337.7055,-337.7055", +"3608.247423,330.8185,-330.8185", +"3681.885125,324.19825,-324.19825", +"3755.522828,317.84475,-317.84475", +"3829.16053,311.73375,-311.73375", +"3902.798233,305.853125,-305.853125", +"3976.435935,300.178625,-300.178625", +"4050.073638,294.722375,-294.722375", +"4123.71134,289.460125,-289.460125", +"4197.349043,284.37975,-284.37975", +"4270.986745,279.48125,-279.48125", +"4344.624448,274.740375,-274.740375", +"4418.26215,270.16925,-270.16925", +"4491.899853,265.7315,-265.7315", +"4565.537555,261.451375,-261.451375", +"4639.175258,257.304625,-257.304625", +"4712.81296,253.279125,-253.279125", +"4786.450663,249.387,-249.387", +"4860.088365,245.604,-245.604", +"4933.726068,241.94225,-241.94225", +"5007.36377,238.3775,-238.3775", +"5081.001473,234.921875,-234.921875", +"5154.639175,231.575375,-231.575375", +"5228.276878,228.31375,-228.31375", +"5301.91458,225.137,-225.137", +"5375.552283,222.05725,-222.05725", +"5449.189985,219.05025,-219.05025", +"5522.827688,216.128125,-216.128125", +"5596.46539,213.290875,-213.290875", +"5670.103093,210.51425,-210.51425", +"5743.740795,207.8225,-207.8225", +"5817.378498,205.191375,-205.191375", +"5891.0162,202.620875,-202.620875", +"5964.653903,200.123125,-200.123125", +"6038.291605,197.686,-197.686", +"6111.929308,195.297375,-195.297375", +"6185.56701,192.969375,-192.969375", +"6259.204713,190.702,-190.702", +"6332.842415,188.483125,-188.483125", +"6406.480118,186.324875,-186.324875", +"6480.11782,184.203,-184.203", +"6553.755523,182.129625,-182.129625", +"6627.393225,180.10475,-180.10475", +"6701.030928,178.128375,-178.128375", +"6774.66863,176.2005,-176.2005", +"6848.306333,174.296875,-174.296875", +"6921.944035,172.44175,-172.44175", +"6995.581738,170.635125,-170.635125", +"7069.21944,168.85275,-168.85275", +"7142.857143,167.10675,-167.10675", +"7216.494845,165.40925,-165.40925", +"7290.132548,163.736,-163.736", +"7363.77025,162.099125,-162.099125" + #endregion data + ); + } + private ElectricMotorFullLoadCurve GetFullLoadCurve(int count) + { + var inputData = GetFullLoadCurveData(); + return ElectricFullLoadCurveReader.Create(inputData, count); + } + private TableData GetEfficiencyMapData() + { + return InputDataHelper.InputDataAsTableData( + "n [rpm] , T [Nm] , P_el [kW]", + #region entries + "0, -485, 0.000", +"0, -461, 0.000", +"0, -437, 0.000", +"0, -412, 0.000", +"0, -388, 0.000", +"0, -364, 0.000", +"0, -340, 0.000", +"0, -315, 0.000", +"0, -291, 0.000", +"0, -267, 0.000", +"0, -243, 0.000", +"0, -218, 0.000", +"0, -194, 0.000", +"0, -170, 0.000", +"0, -146, 0.000", +"0, -121, 0.000", +"0, -97, 0.000", +"0, -73, 0.000", +"0, -48, 0.000", +"0, -24, 0.000", +"0, -5, 0.000", +"0, 5, 0.000", +"0, 24, 0.000", +"0, 48, 0.000", +"0, 73, 0.000", +"0, 97, 0.000", +"0, 121, 0.000", +"0, 146, 0.000", +"0, 170, 0.000", +"0, 194, 0.000", +"0, 218, 0.000", +"0, 243, 0.000", +"0, 267, 0.000", +"0, 291, 0.000", +"0, 315, 0.000", +"0, 340, 0.000", +"0, 364, 0.000", +"0, 388, 0.000", +"0, 412, 0.000", +"0, 437, 0.000", +"0, 461, 0.000", +"0, 485, 0.000", +"49, -485, 0.000", +"49, -461, 0.000", +"49, -437, 0.000", +"49, -412, 0.000", +"49, -388, 0.000", +"49, -364, 0.000", +"49, -340, -0.045", +"49, -315, -0.111", +"49, -291, -0.166", +"49, -267, -0.211", +"49, -243, -0.245", +"49, -218, -0.268", +"49, -194, -0.280", +"49, -170, -0.281", +"49, -146, -0.272", +"49, -121, -0.252", +"49, -97, -0.221", +"49, -73, -0.179", +"49, -48, -0.126", +"49, -24, -0.062", +"49, -5, -0.004", +"49, 5, 0.048", +"49, 24, 0.193", +"49, 48, 0.384", +"49, 73, 0.587", +"49, 97, 0.802", +"49, 121, 1.029", +"49, 146, 1.267", +"49, 170, 1.518", +"49, 194, 1.779", +"49, 218, 2.053", +"49, 243, 2.338", +"49, 267, 2.636", +"49, 291, 2.944", +"49, 315, 3.265", +"49, 340, 3.597", +"49, 364, 3.941", +"49, 388, 4.297", +"49, 412, 4.665", +"49, 437, 5.044", +"49, 461, 5.435", +"49, 485, 5.838", +"492, -485, -20.733", +"492, -461, -19.800", +"492, -437, -18.856", +"492, -412, -17.900", +"492, -388, -16.932", +"492, -364, -15.953", +"492, -340, -14.962", +"492, -315, -13.959", +"492, -291, -12.945", +"492, -267, -11.919", +"492, -243, -10.881", +"492, -218, -9.832", +"492, -194, -8.771", +"492, -170, -7.699", +"492, -146, -6.614", +"492, -121, -5.519", +"492, -97, -4.411", +"492, -73, -3.292", +"492, -48, -2.161", +"492, -24, -1.019", +"492, -5, -0.097", +"492, 5, 0.416", +"492, 24, 1.498", +"492, 48, 2.863", +"492, 73, 4.240", +"492, 97, 5.630", +"492, 121, 7.033", +"492, 146, 8.448", +"492, 170, 9.876", +"492, 194, 11.316", +"492, 218, 12.769", +"492, 243, 14.235", +"492, 267, 15.713", +"492, 291, 17.204", +"492, 315, 18.708", +"492, 340, 20.224", +"492, 364, 21.753", +"492, 388, 23.294", +"492, 412, 24.848", +"492, 437, 26.415", +"492, 461, 27.994", +"492, 485, 29.586", +"984, -485, -44.101", +"984, -461, -42.013", +"984, -437, -39.910", +"984, -412, -37.794", +"984, -388, -35.664", +"984, -364, -33.520", +"984, -340, -31.362", +"984, -315, -29.190", +"984, -291, -27.004", +"984, -267, -24.805", +"984, -243, -22.591", +"984, -218, -20.363", +"984, -194, -18.122", +"984, -170, -15.867", +"984, -146, -13.597", +"984, -121, -11.314", +"984, -97, -9.017", +"984, -73, -6.706", +"984, -48, -4.381", +"984, -24, -2.042", +"984, -5, -0.161", +"984, 5, 0.867", +"984, 24, 2.993", +"984, 48, 5.663", +"984, 73, 8.349", +"984, 97, 11.049", +"984, 121, 13.765", +"984, 146, 16.496", +"984, 170, 19.242", +"984, 194, 22.003", +"984, 218, 24.779", +"984, 243, 27.571", +"984, 267, 30.377", +"984, 291, 33.198", +"984, 315, 36.035", +"984, 340, 38.887", +"984, 364, 41.754", +"984, 388, 44.635", +"984, 412, 47.532", +"984, 437, 50.445", +"984, 461, 53.372", +"984, 485, 56.314", +"1477, -485, -67.122", +"1477, -461, -63.906", +"1477, -437, -60.673", +"1477, -412, -57.422", +"1477, -388, -54.153", +"1477, -364, -50.867", +"1477, -340, -47.563", +"1477, -315, -44.241", +"1477, -291, -40.902", +"1477, -267, -37.545", +"1477, -243, -34.170", +"1477, -218, -30.778", +"1477, -194, -27.368", +"1477, -170, -23.941", +"1477, -146, -20.496", +"1477, -121, -17.033", +"1477, -97, -13.552", +"1477, -73, -10.054", +"1477, -48, -6.539", +"1477, -24, -3.005", +"1477, -5, -0.166", +"1477, 5, 1.383", +"1477, 24, 4.552", +"1477, 48, 8.530", +"1477, 73, 12.528", +"1477, 97, 16.545", +"1477, 121, 20.581", +"1477, 146, 24.636", +"1477, 170, 28.710", +"1477, 194, 32.804", +"1477, 218, 36.916", +"1477, 243, 41.048", +"1477, 267, 45.199", +"1477, 291, 49.369", +"1477, 315, 53.558", +"1477, 340, 57.766", +"1477, 364, 61.994", +"1477, 388, 66.240", +"1477, 412, 70.506", +"1477, 437, 74.791", +"1477, 461, 79.095", +"1477, 485, 83.418", +"1969, -485, -89.780", +"1969, -461, -85.464", +"1969, -437, -81.126", +"1969, -412, -76.766", +"1969, -388, -72.382", +"1969, -364, -67.976", +"1969, -340, -63.546", +"1969, -315, -59.094", +"1969, -291, -54.620", +"1969, -267, -50.122", +"1969, -243, -45.602", +"1969, -218, -41.058", +"1969, -194, -36.492", +"1969, -170, -31.904", +"1969, -146, -27.292", +"1969, -121, -22.658", +"1969, -97, -18.000", +"1969, -73, -13.320", +"1969, -48, -8.618", +"1969, -24, -3.892", +"1969, -5, -0.095", +"1969, 5, 1.980", +"1969, 24, 6.193", +"1969, 48, 11.483", +"1969, 73, 16.796", +"1969, 97, 22.135", +"1969, 121, 27.498", +"1969, 146, 32.886", +"1969, 170, 38.299", +"1969, 194, 43.736", +"1969, 218, 49.199", +"1969, 243, 54.686", +"1969, 267, 60.197", +"1969, 291, 65.734", +"1969, 315, 71.295", +"1969, 340, 76.881", +"1969, 364, 82.492", +"1969, 388, 88.127", +"1969, 412, 93.787", +"1969, 437, 99.472", +"1969, 461, 105.182", +"1969, 485, 110.916", +"2461, -485, -112.056", +"2461, -461, -106.670", +"2461, -437, -101.254", +"2461, -412, -95.808", +"2461, -388, -90.334", +"2461, -364, -84.830", +"2461, -340, -79.296", +"2461, -315, -73.733", +"2461, -291, -68.141", +"2461, -267, -62.519", +"2461, -243, -56.868", +"2461, -218, -51.188", +"2461, -194, -45.478", +"2461, -170, -39.738", +"2461, -146, -33.970", +"2461, -121, -28.172", +"2461, -97, -22.344", +"2461, -73, -16.487", +"2461, -48, -10.601", +"2461, -24, -4.685", +"2461, -5, 0.000", +"2461, 5, 2.679", +"2461, 24, 7.937", +"2461, 48, 14.539", +"2461, 73, 21.173", +"2461, 97, 27.839", +"2461, 121, 34.536", +"2461, 146, 41.266", +"2461, 170, 48.027", +"2461, 194, 54.820", +"2461, 218, 61.646", +"2461, 243, 68.503", +"2461, 267, 75.392", +"2461, 291, 82.313", +"2461, 315, 89.265", +"2461, 340, 96.250", +"2461, 364, 103.267", +"2461, 388, 110.315", +"2461, 412, 117.396", +"2461, 437, 124.508", +"2461, 461, 131.652", +"2461, 485, 138.828", +"2953, -485, -133.934", +"2953, -461, -127.504", +"2953, -437, -121.037", +"2953, -412, -114.532", +"2953, -388, -107.990", +"2953, -364, -101.411", +"2953, -340, -94.794", +"2953, -315, -88.140", +"2953, -291, -81.448", +"2953, -267, -74.719", +"2953, -243, -67.952", +"2953, -218, -61.148", +"2953, -194, -54.306", +"2953, -170, -47.427", +"2953, -146, -40.511", +"2953, -121, -33.557", +"2953, -97, -26.566", +"2953, -73, -19.537", +"2953, -48, -12.471", +"2953, -24, -5.367", +"2953, -5, 0.000", +"2953, 5, 3.497", +"2953, 24, 9.801", +"2953, 48, 17.718", +"2953, 73, 25.676", +"2953, 97, 33.674", +"2953, 121, 41.713", +"2953, 146, 49.793", +"2953, 170, 57.913", +"2953, 194, 66.074", +"2953, 218, 74.275", +"2953, 243, 82.517", +"2953, 267, 90.800", +"2953, 291, 99.123", +"2953, 315, 107.487", +"2953, 340, 115.892", +"2953, 364, 124.337", +"2953, 388, 132.823", +"2953, 412, 141.349", +"2953, 437, 149.916", +"2953, 461, 158.524", +"2953, 485, 167.172", +"3446, -485, -155.396", +"3446, -461, -147.951", +"3446, -437, -140.460", +"3446, -412, -132.921", +"3446, -388, -125.335", +"3446, -364, -117.703", +"3446, -340, -110.023", +"3446, -315, -102.297", +"3446, -291, -94.524", +"3446, -267, -86.703", +"3446, -243, -78.836", +"3446, -218, -70.922", +"3446, -194, -62.961", +"3446, -170, -54.953", +"3446, -146, -46.898", +"3446, -121, -38.797", +"3446, -97, -30.648", +"3446, -73, -22.452", +"3446, -48, -14.210", +"3446, -24, -5.921", +"3446, -5, 0.000", +"3446, 5, 4.454", +"3446, 24, 11.805", +"3446, 48, 21.040", +"3446, 73, 30.325", +"3446, 97, 39.661", +"3446, 121, 49.049", +"3446, 146, 58.487", +"3446, 170, 67.976", +"3446, 194, 77.516", +"3446, 218, 87.107", +"3446, 243, 96.749", +"3446, 267, 106.442", +"3446, 291, 116.185", +"3446, 315, 125.980", +"3446, 340, 135.826", +"3446, 364, 145.722", +"3446, 388, 155.669", +"3446, 412, 165.668", +"3446, 437, 175.717", +"3446, 461, 185.817", +"3446, 485, 195.968", +"3938, -485, -176.425", +"3938, -461, -167.994", +"3938, -437, -159.504", +"3938, -412, -150.956", +"3938, -388, -142.351", +"3938, -364, -133.687", +"3938, -340, -124.966", +"3938, -315, -116.187", +"3938, -291, -107.351", +"3938, -267, -98.456", +"3938, -243, -89.503", +"3938, -218, -80.493", +"3938, -194, -71.425", +"3938, -170, -62.299", +"3938, -146, -53.115", +"3938, -121, -43.873", +"3938, -97, -34.574", +"3938, -73, -25.217", +"3938, -48, -15.801", +"3938, -24, -6.328", +"3938, -5, 0.000", +"3938, 5, 5.568", +"3938, 24, 13.967", +"3938, 48, 24.521", +"3938, 73, 35.138", +"3938, 97, 45.818", +"3938, 121, 56.561", +"3938, 146, 67.366", +"3938, 170, 78.235", +"3938, 194, 89.166", +"3938, 218, 100.159", +"3938, 243, 111.216", +"3938, 267, 122.335", +"3938, 291, 133.517", +"3938, 315, 144.762", +"3938, 340, 156.070", +"3938, 364, 167.440", +"3938, 388, 178.873", +"3938, 412, 190.369", +"3938, 437, 201.927", +"3938, 461, 213.549", +"3938, 485, 225.233", +"4430, -485, -197.004", +"4430, -461, -187.614", +"4430, -437, -178.152", +"4430, -412, -168.621", +"4430, -388, -159.020", +"4430, -364, -149.348", +"4430, -340, -139.606", +"4430, -315, -129.794", +"4430, -291, -119.912", +"4430, -267, -109.959", +"4430, -243, -99.936", +"4430, -218, -89.844", +"4430, -194, -79.680", +"4430, -170, -69.447", +"4430, -146, -59.144", +"4430, -121, -48.770", +"4430, -97, -38.326", +"4430, -73, -27.812", +"4430, -48, -17.228", +"4430, -24, -6.573", +"4430, -5, 0.000", +"4430, 5, 6.859", +"4430, 24, 16.305", +"4430, 48, 28.182", +"4430, 73, 40.135", +"4430, 97, 52.164", +"4430, 121, 64.269", +"4430, 146, 76.450", +"4430, 170, 88.707", +"4430, 194, 101.041", +"4430, 218, 113.451", +"4430, 243, 125.937", +"4430, 267, 138.499", +"4430, 291, 151.138", +"4430, 315, 163.852", +"4430, 340, 176.643", +"4430, 364, 189.510", +"4430, 388, 202.453", +"4430, 412, 215.472", +"4430, 437, 228.567", +"4430, 461, 241.739", +"4430, 485, 254.986", +"4922, -485, -217.116", +"4922, -461, -206.794", +"4922, -437, -196.388", +"4922, -412, -185.899", +"4922, -388, -175.325", +"4922, -364, -164.667", +"4922, -340, -153.925", +"4922, -315, -143.099", +"4922, -291, -132.190", +"4922, -267, -121.196", +"4922, -243, -110.118", +"4922, -218, -98.956", +"4922, -194, -87.710", +"4922, -170, -76.381", +"4922, -146, -64.967", +"4922, -121, -53.469", +"4922, -97, -41.887", +"4922, -73, -30.221", +"4922, -48, -18.472", +"4922, -24, -6.638", +"4922, -5, 0.000", +"4922, 5, 8.344", +"4922, 24, 18.839", +"4922, 48, 32.040", +"4922, 73, 45.333", +"4922, 97, 58.716", +"4922, 121, 72.191", +"4922, 146, 85.757", +"4922, 170, 99.413", +"4922, 194, 113.161", +"4922, 218, 127.001", +"4922, 243, 140.931", +"4922, 267, 154.952", +"4922, 291, 169.065", +"4922, 315, 183.269", +"4922, 340, 197.564", +"4922, 364, 211.950", +"4922, 388, 226.427", +"4922, 412, 240.995", +"4922, 437, 255.655", +"4922, 461, 270.406", +"4922, 485, 285.247", +"5415, -485, -236.743", +"5415, -461, -225.518", +"5415, -437, -214.194", +"5415, -412, -202.771", +"5415, -388, -191.249", +"5415, -364, -179.627", +"5415, -340, -167.906", +"5415, -315, -156.086", +"5415, -291, -144.167", +"5415, -267, -132.149", +"5415, -243, -120.031", +"5415, -218, -107.814", +"5415, -194, -95.497", +"5415, -170, -83.082", +"5415, -146, -70.567", +"5415, -121, -57.953", +"5415, -97, -45.240", +"5415, -73, -32.428", +"5415, -48, -19.516", +"5415, -24, -6.505", +"5415, -5, 0.000", +"5415, 5, 10.043", +"5415, 24, 21.588", +"5415, 48, 36.116", +"5415, 73, 50.751", +"5415, 97, 65.495", +"5415, 121, 80.346", +"5415, 146, 95.305", +"5415, 170, 110.371", +"5415, 194, 125.545", +"5415, 218, 140.827", +"5415, 243, 156.217", +"5415, 267, 171.714", +"5415, 291, 187.319", +"5415, 315, 203.031", +"5415, 340, 218.852", +"5415, 364, 234.779", +"5415, 388, 250.815", +"5415, 412, 266.958", +"5415, 437, 283.209", +"5415, 461, 299.568", +"5415, 485, 316.034", +"5907, -485, -255.867", +"5907, -461, -243.768", +"5907, -437, -231.553", +"5907, -412, -219.222", +"5907, -388, -206.774", +"5907, -364, -194.211", +"5907, -340, -181.532", +"5907, -315, -168.738", +"5907, -291, -155.827", +"5907, -267, -142.800", +"5907, -243, -129.657", +"5907, -218, -116.399", +"5907, -194, -103.024", +"5907, -170, -89.534", +"5907, -146, -75.928", +"5907, -121, -62.205", +"5907, -97, -48.367", +"5907, -73, -34.413", +"5907, -48, -20.343", +"5907, -24, -6.157", +"5907, -5, 0.000", +"5907, 5, 11.974", +"5907, 24, 24.569", +"5907, 48, 40.426", +"5907, 73, 56.409", +"5907, 97, 72.518", +"5907, 121, 88.753", +"5907, 146, 105.113", +"5907, 170, 121.599", +"5907, 194, 138.211", +"5907, 218, 154.949", +"5907, 243, 171.813", +"5907, 267, 188.802", +"5907, 291, 205.917", +"5907, 315, 223.158", +"5907, 340, 240.525", +"5907, 364, 258.017", +"5907, 388, 275.635", +"5907, 412, 293.379", +"5907, 437, 311.249", +"5907, 461, 329.245", +"5907, 485, 347.366", +"6399, -485, -274.473", +"6399, -461, -261.527", +"6399, -437, -248.447", +"6399, -412, -235.232", +"6399, -388, -221.884", +"6399, -364, -208.402", +"6399, -340, -194.786", +"6399, -315, -181.036", +"6399, -291, -167.151", +"6399, -267, -153.133", +"6399, -243, -138.981", +"6399, -218, -124.694", +"6399, -194, -110.274", +"6399, -170, -95.719", +"6399, -146, -81.031", +"6399, -121, -66.208", +"6399, -97, -51.252", +"6399, -73, -36.161", +"6399, -48, -20.936", +"6399, -24, -5.577", +"6399, -5, 0.000", +"6399, 5, 14.156", +"6399, 24, 27.802", +"6399, 48, 44.991", +"6399, 73, 62.325", +"6399, 97, 79.805", +"6399, 121, 97.430", +"6399, 146, 115.201", +"6399, 170, 133.117", +"6399, 194, 151.179", +"6399, 218, 169.386", +"6399, 243, 187.738", +"6399, 267, 206.236", +"6399, 291, 224.879", +"6399, 315, 243.668", +"6399, 340, 262.602", +"6399, 364, 281.682", +"6399, 388, 300.907", +"6399, 412, 320.277", +"6399, 437, 339.793", +"6399, 461, 359.455", +"6399, 485, 379.261", +"6891, -485, -292.541", +"6891, -461, -278.777", +"6891, -437, -264.858", +"6891, -412, -250.787", +"6891, -388, -236.561", +"6891, -364, -222.182", +"6891, -340, -207.650", +"6891, -315, -192.963", +"6891, -291, -178.124", +"6891, -267, -163.130", +"6891, -243, -147.983", +"6891, -218, -132.683", +"6891, -194, -117.228", +"6891, -170, -101.621", +"6891, -146, -85.859", +"6891, -121, -69.944", +"6891, -97, -53.876", +"6891, -73, -37.653", +"6891, -48, -21.278", +"6891, -24, -4.748", +"6891, -5, 0.000", +"6891, 5, 16.608", +"6891, 24, 31.306", +"6891, 48, 49.829", +"6891, 73, 68.518", +"6891, 97, 87.374", +"6891, 121, 106.397", +"6891, 146, 125.587", +"6891, 170, 144.943", +"6891, 194, 164.466", +"6891, 218, 184.155", +"6891, 243, 204.011", +"6891, 267, 224.034", +"6891, 291, 244.223", +"6891, 315, 264.580", +"6891, 340, 285.102", +"6891, 364, 305.792", +"6891, 388, 326.648", +"6891, 412, 347.671", +"6891, 437, 368.860", +"6891, 461, 390.216", +"6891, 485, 411.739", +"7383, -485, -310.056", +"7383, -461, -295.501", +"7383, -437, -280.771", +"7383, -412, -265.867", +"7383, -388, -250.788", +"7383, -364, -235.535", +"7383, -340, -220.106", +"7383, -315, -204.504", +"7383, -291, -188.726", +"7383, -267, -172.775", +"7383, -243, -156.648", +"7383, -218, -140.347", +"7383, -194, -123.871", +"7383, -170, -107.221", +"7383, -146, -90.396", +"7383, -121, -73.397", +"7383, -97, -56.222", +"7383, -73, -38.874", +"7383, -48, -21.350", +"7383, -24, -3.653", +"7383, -5, 0.000", +"7383, 5, 19.348", +"7383, 24, 35.099", +"7383, 48, 54.958", +"7383, 73, 75.007", +"7383, 97, 95.245", +"7383, 121, 115.672", +"7383, 146, 136.289", +"7383, 170, 157.095", +"7383, 194, 178.091", +"7383, 218, 199.276", +"7383, 243, 220.651", +"7383, 267, 242.215", +"7383, 291, 263.969", +"7383, 315, 285.912", +"7383, 340, 308.044", +"7383, 364, 330.366", +"7383, 388, 352.878", +"7383, 412, 375.578", +"7383, 437, 398.469", +"7383, 461, 421.549", +"7383, 485, 444.818", +"7876, -485, -327.000", +"7876, -461, -311.682", +"7876, -437, -296.167", +"7876, -412, -280.456", +"7876, -388, -264.547", +"7876, -364, -248.442", +"7876, -340, -232.139", +"7876, -315, -215.639", +"7876, -291, -198.942", +"7876, -267, -182.048", +"7876, -243, -164.958", +"7876, -218, -147.670", +"7876, -194, -130.185", +"7876, -170, -112.503", +"7876, -146, -94.624", +"7876, -121, -76.548", +"7876, -97, -58.274", +"7876, -73, -39.804", +"7876, -48, -21.137", +"7876, -24, -2.273", +"7876, -5, 0.000", +"7876, 5, 22.396", +"7876, 24, 39.201", +"7876, 48, 60.398", +"7876, 73, 81.810", +"7876, 97, 103.435", +"7876, 121, 125.274", +"7876, 146, 147.327", +"7876, 170, 169.593", +"7876, 194, 192.074", +"7876, 218, 214.768", +"7876, 243, 237.676", +"7876, 267, 260.798", +"7876, 291, 284.134", +"7876, 315, 307.683", +"7876, 340, 331.447", +"7876, 364, 355.424", +"7876, 388, 379.615", +"7876, 412, 404.019", +"7876, 437, 428.638", +"7876, 461, 453.470", +"7876, 485, 478.516", +"8368, -485, -343.355", +"8368, -461, -327.303", +"8368, -437, -311.030", +"8368, -412, -294.536", +"8368, -388, -277.822", +"8368, -364, -260.886", +"8368, -340, -243.730", +"8368, -315, -226.352", +"8368, -291, -208.754", +"8368, -267, -190.935", +"8368, -243, -172.895", +"8368, -218, -154.634", +"8368, -194, -136.152", +"8368, -170, -117.449", +"8368, -146, -98.525", +"8368, -121, -79.380", +"8368, -97, -60.014", +"8368, -73, -40.428", +"8368, -48, -20.620", +"8368, -24, -0.592", +"8368, -5, 0.000", +"8368, 5, 25.770", +"8368, 24, 43.629", +"8368, 48, 66.167", +"8368, 73, 88.946", +"8368, 97, 111.964", +"8368, 121, 135.221", +"8368, 146, 158.719", +"8368, 170, 182.456", +"8368, 194, 206.433", +"8368, 218, 230.649", +"8368, 243, 255.106", +"8368, 267, 279.802", +"8368, 291, 304.738", +"8368, 315, 329.913", +"8368, 340, 355.328", +"8368, 364, 380.983", +"8368, 388, 406.878", +"8368, 412, 433.012", +"8368, 437, 459.386", +"8368, 461, 486.000", +"8368, 485, 512.853", +"8860, -485, -359.104", +"8860, -461, -342.346", +"8860, -437, -325.341", +"8860, -412, -308.091", +"8860, -388, -290.594", +"8860, -364, -272.851", +"8860, -340, -254.862", +"8860, -315, -236.626", +"8860, -291, -218.144", +"8860, -267, -199.416", +"8860, -243, -180.442", +"8860, -218, -161.221", +"8860, -194, -141.755", +"8860, -170, -122.042", +"8860, -146, -102.082", +"8860, -121, -81.877", +"8860, -97, -61.425", +"8860, -73, -40.727", +"8860, -48, -19.783", +"8860, -24, 0.000", +"8860, -5, 0.000", +"8860, 5, 29.489", +"8860, 24, 48.402", +"8860, 48, 72.284", +"8860, 73, 96.433", +"8860, 97, 120.849", +"8860, 121, 145.533", +"8860, 146, 170.484", +"8860, 170, 195.701", +"8860, 194, 221.186", +"8860, 218, 246.939", +"8860, 243, 272.958", +"8860, 267, 299.245", +"8860, 291, 325.798", +"8860, 315, 352.619", +"8860, 340, 379.708", +"8860, 364, 407.063", +"8860, 388, 434.685", +"8860, 412, 462.575", +"8860, 437, 490.732", +"8860, 461, 519.156", +"8860, 485, 547.847", +"9352, -485, -374.230", +"9352, -461, -356.794", +"9352, -437, -339.084", +"9352, -412, -321.102", +"9352, -388, -302.847", +"9352, -364, -284.319", +"9352, -340, -265.517", +"9352, -315, -246.443", +"9352, -291, -227.096", +"9352, -267, -207.475", +"9352, -243, -187.582", +"9352, -218, -167.416", +"9352, -194, -146.976", +"9352, -170, -126.264", +"9352, -146, -105.279", +"9352, -121, -84.021", +"9352, -97, -62.489", +"9352, -73, -40.685", +"9352, -48, -18.608", +"9352, -24, 0.000", +"9352, -5, 0.000", +"9352, 5, 33.571", +"9352, 24, 53.540", +"9352, 48, 78.768", +"9352, 73, 104.291", +"9352, 97, 130.111", +"9352, 121, 156.228", +"9352, 146, 182.640", +"9352, 170, 209.349", +"9352, 194, 236.354", +"9352, 218, 263.655", +"9352, 243, 291.252", +"9352, 267, 319.146", +"9352, 291, 347.335", +"9352, 315, 375.821", +"9352, 340, 404.604", +"9352, 364, 433.682", +"9352, 388, 463.057", +"9352, 412, 492.728", +"9352, 437, 522.695", +"9352, 461, 552.958", +"9352, 485, 583.518", +"9845, -485, -388.716", +"9845, -461, -370.630", +"9845, -437, -352.242", +"9845, -412, -333.553", +"9845, -388, -314.563", +"9845, -364, -295.272", +"9845, -340, -275.680", +"9845, -315, -255.786", +"9845, -291, -235.591", +"9845, -267, -215.095", +"9845, -243, -194.298", +"9845, -218, -173.200", +"9845, -194, -151.800", +"9845, -170, -130.099", +"9845, -146, -108.097", +"9845, -121, -85.794", +"9845, -97, -63.190", +"9845, -73, -40.284", +"9845, -48, -17.077", +"9845, -24, 0.000", +"9845, -5, 0.000", +"9845, 5, 38.036", +"9845, 24, 59.061", +"9845, 48, 85.637", +"9845, 73, 112.539", +"9845, 97, 139.768", +"9845, 121, 167.324", +"9845, 146, 195.207", +"9845, 170, 223.417", +"9845, 194, 251.953", +"9845, 218, 280.816", +"9845, 243, 310.007", +"9845, 267, 339.523", +"9845, 291, 369.367", +"9845, 315, 399.538", +"9845, 340, 430.035", +"9845, 364, 460.859", +"9845, 388, 492.010", +"9845, 412, 523.488", +"9845, 437, 555.293", +"9845, 461, 587.424", +"9845, 485, 619.883" + #endregion data + ).ApplyFactor(ElectricMotorMapReader.Fields.PowerElectrical, 1E3); //Convert from kW to W + } + + private EfficiencyMap GetEfficiencyMap(int count) + { + return ElectricMotorMapReader.Create(GetEfficiencyMapData(), count, ExecutionMode.Declaration); + } + private void SetVelocityDropLookupData(PEVAMTShiftStrategy shiftStrategy) + { + //"StartVelocity [km/h], Gradient [-], EndVelocity [km/h]" + var data = new[] { + new[] { 5.0, -0.0997, 9.061522965237558 }, + new[] { 5.0, -0.0798, 7.76698080079411 }, + new[] { 5.0, -0.0599, 6.46583777913701 }, + new[] { 5.0, -0.0400, 5.1596021788785045 }, + new[] { 5.0, -0.0200, 3.8498121019126907 }, + new[] { 5.0, 0.0000, 2.5380265159468918 }, + new[] { 5.0, 0.0200, 1.2258160477557427 }, + new[] { 5.0, 0.0400, 0.0 }, + new[] { 5.0, 0.0599, 0.0 }, + new[] { 5.0, 0.0798, 0.0 }, + new[] { 5.0, 0.0997, 0.0 }, + new[] { 10.0, -0.0997, 14.807789640888302 }, + new[] { 10.0, -0.0798, 13.474253785811362 }, + new[] { 10.0, -0.0599, 12.133880027250777 }, + new[] { 10.0, -0.0400, 10.788221550084467 }, + new[] { 10.0, -0.0200, 9.438862432338068 }, + new[] { 10.0, 0.0000, 8.087408432114643 }, + new[] { 10.0, 0.0200, 6.735477499784416 }, + new[] { 10.0, 0.0400, 5.384690105076845 }, + new[] { 10.0, 0.0599, 4.036659549786269 }, + new[] { 10.0, 0.0798, 2.6929823705748137 }, + new[] { 10.0, 0.0997, 1.3552289800549435 }, + new[] { 20.0, -0.0997, 25.061542153872097 }, + new[] { 20.0, -0.0798, 23.72002987685605 }, + new[] { 20.0, -0.0599, 22.371630788642932 }, + new[] { 20.0, -0.0400, 21.017907257116025 }, + new[] { 20.0, -0.0200, 19.660452757813403 }, + new[] { 20.0, 0.0000, 18.30088261992287 }, + new[] { 20.0, 0.0200, 16.94082447048767 }, + new[] { 20.0, 0.0400, 15.581908518759507 }, + new[] { 20.0, 0.0599, 14.225757795590708 }, + new[] { 20.0, 0.0798, 12.873978508374211 }, + new[] { 20.0, 0.0997, 11.528150617530041 }, + new[] { 30.000000000000004, -0.0997, 35.091774208140095 }, + new[] { 30.000000000000004, -0.0798, 33.750904327320896 }, + new[] { 30.000000000000004, -0.0599, 32.40315158162777 }, + new[] { 30.000000000000004, -0.0400, 31.050077596965064 }, + new[] { 30.000000000000004, -0.0200, 29.69327509188113 }, + new[] { 30.000000000000004, 0.0000, 28.33435862498606 }, + new[] { 30.000000000000004, 0.0200, 26.974955046566407 }, + new[] { 30.000000000000004, 0.0400, 25.616693776603913 }, + new[] { 30.000000000000004, 0.0599, 24.261197065863925 }, + new[] { 30.000000000000004, 0.0798, 22.91007034016412 }, + new[] { 30.000000000000004, 0.0997, 21.56489279686667 }, + new[] { 40.0, -0.0997, 45.024018797189854 }, + new[] { 40.0, -0.0798, 43.68636622428101 }, + new[] { 40.0, -0.0599, 42.34185052441486 }, + new[] { 40.0, -0.0400, 40.99202962224952 }, + new[] { 40.0, -0.0200, 39.63849244500093 }, + new[] { 40.0, 0.0000, 38.282849690992855 }, + new[] { 40.0, 0.0200, 36.926724305651554 }, + new[] { 40.0, 0.0400, 35.57174178507285 }, + new[] { 40.0, 0.0599, 34.21952045137207 }, + new[] { 40.0, 0.0798, 32.87166183129923 }, + new[] { 40.0, 0.0997, 31.5297412694979 }, + new[] { 50.0, -0.0997, 54.652157586769704 }, + new[] { 50.0, -0.0798, 53.319266704395716 }, + new[] { 50.0, -0.0599, 51.97954186606304 }, + new[] { 50.0, -0.0400, 50.634535516787736 }, + new[] { 50.0, -0.0200, 49.28583097196263 }, + new[] { 50.0, 0.0000, 47.93503321632867 }, + new[] { 50.0, 0.0200, 46.583759417454765 }, + new[] { 50.0, 0.0400, 45.23362925944123 }, + new[] { 50.0, 0.0599, 43.88625525588574 }, + new[] { 50.0, 0.0798, 42.54323315977748 }, + new[] { 50.0, 0.0997, 41.20613261641401 }, + new[] { 60.00000000000001, -0.0997, 64.2503607025971 }, + new[] { 60.00000000000001, -0.0798, 62.91932863058169 }, + new[] { 60.00000000000001, -0.0599, 61.58156853535776 }, + new[] { 60.00000000000001, -0.0400, 60.23862904729555 }, + new[] { 60.00000000000001, -0.0200, 58.89369896300112 }, + new[] { 60.00000000000001, 0.0000, 57.547040626925885 }, + new[] { 60.00000000000001, 0.0200, 56.199911833784675 }, + new[] { 60.00000000000001, 0.0400, 54.85392730356455 }, + new[] { 60.00000000000001, 0.0599, 53.510694584916905 }, + new[] { 60.00000000000001, 0.0798, 52.17180450267632 }, + new[] { 60.00000000000001, 0.0997, 50.83882182989668 }, + new[] { 70.0, -0.0997, 73.78388063954164 }, + new[] { 70.0, -0.0798, 72.45700102808648 }, + new[] { 70.0, -0.0599, 71.12341092304165 }, + new[] { 70.0, -0.0400, 69.78459543842656 }, + new[] { 70.0, -0.0200, 68.44188526693415 }, + new[] { 70.0, 0.0000, 67.09719334997524 }, + new[] { 70.0, 0.0200, 65.75212749798493 }, + new[] { 70.0, 0.0400, 64.40829754257321 }, + new[] { 70.0, 0.0599, 63.06730571969745 }, + new[] { 70.0, 0.0798, 61.73073716025881 }, + new[] { 70.0, 0.0997, 60.40015062055851 }, + new[] { 80.0, -0.0997, 83.25457689135129 }, + new[] { 80.0, -0.0798, 81.93182852399568 }, + new[] { 80.0, -0.0599, 80.60238880559001 }, + new[] { 80.0, -0.0400, 79.2676325992058 }, + new[] { 80.0, -0.0200, 77.92916666616652 }, + new[] { 80.0, 0.0000, 76.58872134590663 }, + new[] { 80.0, 0.0200, 75.24790011046437 }, + new[] { 80.0, 0.0400, 73.90830846424944 }, + new[] { 80.0, 0.0599, 72.57154434889891 }, + new[] { 80.0, 0.0798, 71.23918865436896 }, + new[] { 80.0, 0.0997, 69.91277394305271 }, + }; + var entries = new List<VelocitySpeedGearshiftPreprocessor.Entry>(); + foreach (var d in data) { + entries.Add(new VelocitySpeedGearshiftPreprocessor.Entry() { + StartVelocity = d[0].KMPHtoMeterPerSecond(), + Gradient = d[1].SI<Radian>(), + EndVelocity = d[2].KMPHtoMeterPerSecond(), + }); + } + + shiftStrategy.VelocityDropData.Data = entries.ToArray(); + + } + + } +} + + \ No newline at end of file -- GitLab From c29469f62348fced31e38d9900e776e7349a2e8b Mon Sep 17 00:00:00 2001 From: "VKMTHD\\haraldmartini" <martini@ivt.tugraz.at> Date: Tue, 25 Mar 2025 11:10:09 +0100 Subject: [PATCH 22/22] updated shiftstrategy testcases make sure mock gearboxes are used --- .../AMTShiftStrategyOptimizedTests.cs | 33 +- .../AMTShiftStrategyTests.cs | 200 +- .../APTNShiftStrategyTests.cs | 25 +- .../ATShiftStrategyOptimizedTests.cs | 1994 +++++++---------- .../GearShiftStrategy/MTShiftStrategyTests.cs | 26 +- .../PEVAMTShiftStrategyTests.cs | 46 +- .../Models/SimulationComponent/IGearbox.cs | 7 +- .../Impl/Gearbox/APTGearbox.cs | 4 + .../Impl/Shiftstrategies/AMTShiftStrategy.cs | 24 +- .../ATShiftStrategyOptimized.cs | 7 +- .../Impl/TorqueConverter.cs | 2 +- 11 files changed, 1048 insertions(+), 1320 deletions(-) diff --git a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/AMTShiftStrategyOptimizedTests.cs b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/AMTShiftStrategyOptimizedTests.cs index 886a5e6340..45ca4700fb 100644 --- a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/AMTShiftStrategyOptimizedTests.cs +++ b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/AMTShiftStrategyOptimizedTests.cs @@ -190,22 +190,22 @@ TestCase(8, 4, 15000, 200, true),] // } // // - [TestCase] - public void GetMocksTest() - { - // the first element 0.0 is just a placeholder for axlegear, not used in this test - var ratios = new[] { 0.0, 6.38, 4.63, 3.84, 2.59, 1.86, 1.35, 1, 0.76 }; - - var mockContainer = GetMocks(ratios, - out var runData, - out var testPowertrain); - - var container = mockContainer.Object; - var createdTestPowertrain = container.SimplePowertrainBuilder.CreateTestPowertrain(container, false); - - Assert.NotNull(createdTestPowertrain.Container.GearboxOutPort); - Assert.NotNull(createdTestPowertrain); - } + // [TestCase] + // public void GetMocksTest() + // { + // // the first element 0.0 is just a placeholder for axlegear, not used in this test + // var ratios = new[] { 0.0, 6.38, 4.63, 3.84, 2.59, 1.86, 1.35, 1, 0.76 }; + // + // var mockContainer = GetMocks(ratios, + // out var runData, + // out var testPowertrain); + // + // var container = mockContainer.Object; + // var createdTestPowertrain = container.SimplePowertrainBuilder.CreateTestPowertrain(container, false); + // + // Assert.NotNull(createdTestPowertrain.Container.GearboxOutPort); + // Assert.NotNull(createdTestPowertrain); + // } [TestCase(1, 2, 100, 900, true)] @@ -621,7 +621,6 @@ TestCase(8, 4, 15000, 200, true),] var amtGearbox = new Mock<IAMTGearbox>(MockBehavior.Strict); amtGearbox.Name = "AMT_Gearbox"; var gbx = amtGearbox.As<IGearbox>(); - gbx.Setup(g => g.LastUpshift).Returns(-double.MaxValue.SI<Second>()); gbx.Setup(g => g.LastDownshift).Returns(-double.MaxValue.SI<Second>()); return gbx; diff --git a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/AMTShiftStrategyTests.cs b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/AMTShiftStrategyTests.cs index 19c047ba8c..fdf9359028 100644 --- a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/AMTShiftStrategyTests.cs +++ b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/AMTShiftStrategyTests.cs @@ -1,9 +1,9 @@ -using Moq; +using Microsoft.VisualStudio.TestPlatform.ObjectModel; +using Moq; using NUnit.Framework; using TUGraz.VectoCommon.InputData; using TUGraz.VectoCommon.Models; using TUGraz.VectoCommon.Utils; -using TUGraz.VectoCore.Configuration; using TUGraz.VectoCore.InputData.Reader.ComponentData; using TUGraz.VectoCore.Models.Connector.Ports.Impl; using TUGraz.VectoCore.Models.Declaration; @@ -20,6 +20,7 @@ using TUGraz.VectoCore.Models.SimulationComponent.Impl.Gearbox; using TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies; using TUGraz.VectoCore.Tests.Utils; using Assert = NUnit.Framework.Assert; +using Constants = TUGraz.VectoCore.Configuration.Constants; namespace TUGraz.Vecto.UnitTests.TestCases.Components.GearShiftStrategy; @@ -330,37 +331,83 @@ TestCase(8, 4, 15000, 200, true),] Assert.AreEqual(newGear, shiftStrategy.NextGear.Gear); } + private Mock<ISimpleVehicleContainer> GetSimpleVehicleContainer(VectoRunData runData, out Mock<ITestPowertrainTransmission> gbx) + { + var simpleContainer = new Mock<ISimpleVehicleContainer>(); + + simpleContainer.Setup(c => c.RunData).Returns(runData); + simpleContainer.Setup(c => c.PowertrainInfo.HasCombustionEngine).Returns(true); + + gbx = GetTestGearbox(runData.GearboxData.Gears); + + simpleContainer.Setup(c => c.GearboxOutPort).Returns(gbx.Object); + + return simpleContainer; + } + + private Mock<ITestPowertrainTransmission> GetTestGearbox(Dictionary<uint, GearData> ratios) + { + var gbx = new Mock<ITestPowertrainTransmission>(); + + gbx.Setup(g => g.LastUpshift).Returns(-double.MaxValue.SI<Second>()); + gbx.Setup(g => g.LastDownshift).Returns(-double.MaxValue.SI<Second>()); + + GearshiftPosition gear = null; + gbx.SetupGet(g => g.Gear).Returns(() => { + + return gear; + }); + gbx.SetupSet(g => g.SetGear = It.IsAny<GearshiftPosition>()) + .Callback<GearshiftPosition>(p => { + gear = p; + }); + + + GearshiftPosition nextGear = null; + gbx.SetupGet(g => g.NextGear).Returns(() => nextGear); + gbx.SetupSet(g => g.SetNextGear = It.IsAny<GearshiftPosition>()) + .Callback<GearshiftPosition>(p => nextGear = p); + + gbx.Setup(p => p.Initialize(It.IsAny<NewtonMeter>(), + It.IsAny<PerSecond>())).Returns((NewtonMeter tq, PerSecond rpm) => { + return new ResponseSuccess(this) + { + Engine = { + EngineSpeed = rpm, + PowerRequest = tq * rpm, + }, + }; + }); + + + gbx.Setup(g => g.Request(It.IsAny<Second>(), It.IsAny<Second>(), It.IsAny<NewtonMeter>(), It.IsAny<PerSecond>(), + It.IsAny<bool>())) + .Returns((Second absTime, Second dt, NewtonMeter t, PerSecond n, bool dryRun) => { + var ratio = gbx.Object.Gear == null ? 1.0 : ratios[gbx.Object.Gear.Gear].Ratio; + return dryRun + ? new ResponseDryRun(this) { + Engine = { + PowerRequest = n * t, EngineSpeed = n * ratio, + DynamicFullLoadPower = (t / ratio + 2300.SI<NewtonMeter>()) * n * ratio, + }, + Clutch = { PowerRequest = n * t } + } + : new ResponseSuccess(this) { + Engine = { PowerRequest = n * t, EngineSpeed = n * ratio }, + Clutch = { PowerRequest = n * t } + }; + }); + return gbx; + } private Mock<ITestPowertrain> GetMockTestPowertrain(VectoRunData runData) { var testPt = new Mock<ITestPowertrain>(); - var tCnt = new Mock<ISimpleVehicleContainer>(); - tCnt.Setup(c => c.RunData).Returns(runData); - var tPi = new Mock<IPowertainInfo>(); - tPi.Setup(p => p.HasCombustionEngine).Returns(true); - tCnt.Setup(c => c.PowertrainInfo).Returns(tPi.Object); - var tGbx = new Mock<ITestPowertrainTransmission>(); - testPt.Setup(t => t.Gearbox).Returns(tGbx.Object); - tGbx.Setup(g => g.Initialize(It.IsAny<NewtonMeter>(), It.IsAny<PerSecond>())) - .Returns((NewtonMeter t, PerSecond n) => new ResponseSuccess(this) { - Engine = { PowerRequest = n * t, EngineSpeed = n }, - Clutch = { PowerRequest = n * t } - }); - tGbx.Setup(g => g.Request(It.IsAny<Second>(), It.IsAny<Second>(), It.IsAny<NewtonMeter>(), It.IsAny<PerSecond>(), - It.IsAny<bool>())) - .Returns((Second absTime, Second dt, NewtonMeter t, PerSecond n, bool dryRun) => new ResponseSuccess(this) { - Engine = { PowerRequest = n * t, EngineSpeed = n }, - Clutch = { PowerRequest = n * t } - }); - tGbx.Setup(g => g.Request(It.IsAny<Second>(), It.IsAny<Second>(), It.IsAny<NewtonMeter>(), It.IsAny<PerSecond>(), - It.IsAny<bool>())) - .Returns((Second absTime, Second dt, NewtonMeter t, PerSecond n, bool dryRun) => dryRun ? - new ResponseDryRun(this) { - Engine = { PowerRequest = n * t, EngineSpeed = n }, - Clutch = { PowerRequest = n * t } - }: new ResponseSuccess(this) { - Engine = { PowerRequest = n * t, EngineSpeed = n }, - Clutch = { PowerRequest = n * t } - }); + + var simpleContainer = GetSimpleVehicleContainer(runData, out var gbx); + // var tCnt = new Mock<ISimpleVehicleContainer>(); + testPt.Setup(t => t.Container).Returns(simpleContainer.Object); + testPt.Setup(t => t.Gearbox).Returns(gbx.Object); + var tEng = new Mock<ITestpowertrainCombustionEngine>(); testPt.Setup(t => t.CombustionEngine).Returns(tEng.Object); tEng.Setup(e => e.EngineStationaryFullPower(It.IsAny<PerSecond>())) @@ -375,13 +422,11 @@ TestCase(8, 4, 15000, 200, true),] var veh = new Mock<IVehicleInfo>(); veh.Setup(v => v.VehicleSpeed).Returns(10.SI<MeterPerSecond>()); container.Setup(c => c.VehicleInfo).Returns(veh.Object); - var eng = new Mock<IEngineInfo>(); - container.Setup(c => c.EngineInfo).Returns(eng.Object); - eng.Setup(e => e.EngineIdleSpeed).Returns(runData.EngineData.IdleSpeed); - eng.Setup(e => e.EngineRatedSpeed).Returns(runData.EngineData.FullLoadCurves.First().Value.RatedSpeed); - eng.Setup(e => e.EngineN95hSpeed).Returns(runData.EngineData.FullLoadCurves.First().Value.N95hSpeed); - eng.Setup(e => e.EngineStationaryFullPower(It.IsAny<PerSecond>())) - .Returns((PerSecond n) => runData.EngineData.FullLoadCurves[0].FullLoadStationaryPower(n)); + + //EngineInfo + var eng = GetEngineInfo(runData); + container.Setup(c => c.EngineInfo).Returns(eng.Object); + var ci = new Mock<IDrivingCycleInfo>(); container.Setup(c => c.DrivingCycleInfo).Returns(ci.Object); var di = new Mock<IDriverInfo>(); @@ -396,14 +441,11 @@ TestCase(8, 4, 15000, 200, true),] var pi = new Mock<IPowertainInfo>(); pi.Setup(p => p.HasCombustionEngine).Returns(true); container.Setup(c => c.PowertrainInfo).Returns(pi.Object); - var vi = new Mock<IVehicleInfo>(); - vi.Setup(v => v.AirDragResistance(It.IsAny<MeterPerSecond>(), It.IsAny<MeterPerSecond>())) - .Returns(0.SI<Newton>()); - vi.Setup(v => v.RollingResistance(It.IsAny<Radian>())).Returns(0.SI<Newton>()); - vi.Setup(v => v.SlopeResistance(It.IsAny<Radian>())).Returns(0.SI<Newton>()); - vi.Setup(v => v.VehicleSpeed).Returns(30.KMPHtoMeterPerSecond()); - vi.Setup(v => v.TotalMass).Returns(12000.SI<Kilogram>()); + + var vi = GetVehicleInfo(); container.Setup(c => c.VehicleInfo).Returns(vi.Object); + + var wi = new Mock<IWheelsInfo>(); container.Setup(c => c.WheelsInfo).Returns(wi.Object); wi.Setup(w => w.ReducedMassWheels).Returns(0.SI<Kilogram>()); @@ -413,13 +455,65 @@ TestCase(8, 4, 15000, 200, true),] return container; } - private Mock<AMTGearbox> GetMockGearbox(Mock<IVehicleContainer> container) + private static Mock<IVehicleInfo> GetVehicleInfo() + { + var vi = new Mock<IVehicleInfo>(); + vi.Setup(v => v.AirDragResistance(It.IsAny<MeterPerSecond>(), It.IsAny<MeterPerSecond>())) + .Returns(0.SI<Newton>()); + vi.Setup(v => v.RollingResistance(It.IsAny<Radian>())).Returns(0.SI<Newton>()); + vi.Setup(v => v.SlopeResistance(It.IsAny<Radian>())).Returns(0.SI<Newton>()); + vi.Setup(v => v.VehicleSpeed).Returns(30.KMPHtoMeterPerSecond()); + vi.Setup(v => v.TotalMass).Returns(12000.SI<Kilogram>()); + return vi; + } + + private static Mock<IEngineInfo> GetEngineInfo(VectoRunData runData) { - var gbx = new Mock<AMTGearbox>(container.Object, null); - var ratios = container.Object.RunData.GearboxData.Gears; + var eng = new Mock<IEngineInfo>(); + + eng.Setup(e => e.EngineIdleSpeed).Returns(runData.EngineData.IdleSpeed); + eng.Setup(e => e.EngineRatedSpeed).Returns(runData.EngineData.FullLoadCurves.First().Value.RatedSpeed); + eng.Setup(e => e.EngineN95hSpeed).Returns(runData.EngineData.FullLoadCurves.First().Value.N95hSpeed); + eng.Setup(e => e.EngineStationaryFullPower(It.IsAny<PerSecond>())) + .Returns((PerSecond n) => runData.EngineData.FullLoadCurves[0].FullLoadStationaryPower(n)); + return eng; + } + + private Mock<ITestPowertrainTransmission> GetMockTestGearbox(Dictionary<uint, GearData> ratios) + { + var gbx = new Mock<ITestPowertrainTransmission>(); + gbx.Setup(g => g.LastUpshift).Returns(-double.MaxValue.SI<Second>()); gbx.Setup(g => g.LastDownshift).Returns(-double.MaxValue.SI<Second>()); - gbx.SetupProperty(g => g.Gear); + + GearshiftPosition gear = null; + gbx.SetupGet(g => g.Gear).Returns(() => { + + return gear; + }); + gbx.SetupSet(g => g.SetGear = It.IsAny<GearshiftPosition>()) + .Callback<GearshiftPosition>(p => { + gear = p; + }); + + + GearshiftPosition nextGear = null; + gbx.SetupGet(g => g.NextGear).Returns(() => nextGear); + gbx.SetupSet(g => g.SetNextGear = It.IsAny<GearshiftPosition>()) + .Callback<GearshiftPosition>(p => nextGear = p); + + gbx.Setup(p => p.Initialize(It.IsAny<NewtonMeter>(), + It.IsAny<PerSecond>())).Returns((NewtonMeter tq, PerSecond rpm) => { + return new ResponseSuccess(this) + { + Engine = { + EngineSpeed = rpm, + PowerRequest = tq * rpm, + }, + }; + }); + + gbx.Setup(g => g.Request(It.IsAny<Second>(), It.IsAny<Second>(), It.IsAny<NewtonMeter>(), It.IsAny<PerSecond>(), It.IsAny<bool>())) .Returns((Second absTime, Second dt, NewtonMeter t, PerSecond n, bool dryRun) => { @@ -439,6 +533,16 @@ TestCase(8, 4, 15000, 200, true),] }); return gbx; } + + + private Mock<IAMTGearbox> GetMockGearbox(Mock<IVehicleContainer> container) + { + //Make sure no method that is not explicitly mocked is called + var gbx = new Mock<IAMTGearbox>(MockBehavior.Strict); + gbx.Setup(g => g.LastUpshift).Returns(-double.MaxValue.SI<Second>()); + gbx.Setup(g => g.LastDownshift).Returns(-double.MaxValue.SI<Second>()); + return gbx; + } private static VectoRunData GetRunData(double[] ratios) { diff --git a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/APTNShiftStrategyTests.cs b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/APTNShiftStrategyTests.cs index 69476d7097..d3d72531ab 100644 --- a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/APTNShiftStrategyTests.cs +++ b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/APTNShiftStrategyTests.cs @@ -377,27 +377,20 @@ namespace TUGraz.Vecto.UnitTests.TestCases.Components.GearShiftStrategy - private PEVAMTShiftStrategy GetShiftStrategyAndGearbox(Mock<IVehicleContainer> container, out IEPCGearbox gearbox) + private APTNShiftStrategy GetShiftStrategyAndGearbox(Mock<IVehicleContainer> container, out Mock<IIEPCGearbox> gearbox) { var shiftStrategy = new APTNShiftStrategy(container.Object); - var gbxFactory = new Mock<IIEPCGearboxFactory>(); - gbxFactory.Setup(g => g.CreateIEPCGearbox( - false, - It.IsAny<IVehicleContainer>(), - It.IsAny<IShiftStrategy>())).Returns( - (bool singleSpeed, IVehicleContainer container, IShiftStrategy shiftStrategy) => { - return new IEPCGearboxMultipleGears(container, shiftStrategy); - }); + var gbx = new Mock<IIEPCGearbox>(MockBehavior.Strict); + gbx.Name = "MockGearbox"; + gbx.Setup(g => g.LastUpshift).Returns(-double.MaxValue.SI<Second>()); + gbx.Setup(g => g.LastDownshift).Returns(-double.MaxValue.SI<Second>()); - gearbox = new IEPCGearbox(container.Object, - shiftStrategy, gbxFactory.Object); - + shiftStrategy.Gearbox = gbx.Object; SetVelocityDropLookupData(shiftStrategy); - - container.Setup(c => c.GearboxInfo).Returns(gearbox); - - + container.Setup(c => c.GearboxInfo).Returns(gbx.Object); + + gearbox = gbx; return shiftStrategy; } diff --git a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyOptimizedTests.cs b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyOptimizedTests.cs index 7e05644e5c..5ce9fd15e7 100644 --- a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyOptimizedTests.cs +++ b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/ATShiftStrategyOptimizedTests.cs @@ -2,6 +2,7 @@ using System.Globalization; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; +using System.Runtime.CompilerServices; using System.Security.Cryptography; using Moq; using NUnit.Framework; @@ -57,12 +58,11 @@ public class ATShiftStrategyOptimizedTests var gearRatios = new[] { 3.4, 1.9, 1.42, 1.0, 0.7, 0.62 }; var vehicleContainer = GetMockVehicleContainer( speedKmh: vehicleSpeed, - DrivingBehavior.Accelerating, - gearRatios, - out _, - out var runData, - out _, - out _); + driverBehavior: DrivingBehavior.Accelerating, + gearRatios: gearRatios, + inputData: out _, + runData: out var runData, + simplePt: out _); var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx, out _); var angularVelocity = GetAngularVelocityBySpeed(vehicleSpeed, runData); @@ -74,488 +74,97 @@ public class ATShiftStrategyOptimizedTests Assert.AreEqual(expectedGear, response.Gear); } + + - private Mock<IVehicleContainer> GetMockVehicleContainer(double speedKmh, DrivingBehavior driverBehavior, - double[] gearRatios, - out Mock<IVehicleDeclarationInputData> inputData, out VectoRunData runData, out GearboxData gearboxData, - out Mock<ISimpleVehicleContainer> simplePt) - { - var vehicleContainer = new Mock<IVehicleContainer>(); - - inputData = GetMockInputData(gearRatios); - runData = GetDummyVectoRunData(inputData.Object); - - vehicleContainer.Setup(c => c.RunData).Returns(runData); - - - //Testpowertrain - var testPowertrain = GetMockTestPowertrain( - runData, - out simplePt); - - vehicleContainer.Setup(c => c.SimplePowertrainBuilder.CreateTestPowertrain(It.IsAny<IVehicleContainer>(), - It.IsAny<bool>())).Returns(testPowertrain.Object); - - //VehicleInfo - vehicleContainer.Setup(c => c.VehicleInfo) - .Returns(GetVehicleInfo(speedKmh.KMPHtoMeterPerSecond()).Object); - - //EngineInfo - vehicleContainer.Setup(c => c.EngineInfo).Returns(GetEngineInfo(vehicleContainer, runData)); - - //AxleGearInfo - var axleGearInfo = new Mock<IAxlegearInfo>(); - vehicleContainer.Setup(c => c.AxlegearInfo).Returns(axleGearInfo.Object); - axleGearInfo.Setup(a => a.AxlegearLoss()).Returns(0.SI<Watt>()); - - //WheelsInfo - var wi = new Mock<IWheelsInfo>(); - vehicleContainer.Setup(c => c.WheelsInfo).Returns(wi.Object); - wi.Setup(w => w.ReducedMassWheels).Returns(0.SI<Kilogram>()); - - //Cycle Info - var cycleInfo = new Mock<IDrivingCycleInfo>(); - vehicleContainer.Setup(c => c.DrivingCycleInfo).Returns(cycleInfo.Object); - cycleInfo.Setup(c => c.CycleData).Returns( - GetCycleData()); - cycleInfo.Setup(c => c.RoadGradient).Returns(0.SI<Radian>()); - - - cycleInfo.Setup(c => c.CycleLookAhead(It.IsAny<Meter>())).Returns(new DrivingCycleData.DrivingCycleEntry() { - Altitude = 0.SI<Meter>() - }); - cycleInfo.Setup(c => c.Altitude).Returns(0.SI<Meter>()); - - //DriverINfo - vehicleContainer.Setup(v => v.DriverInfo.DriverBehavior).Returns(driverBehavior); - var acc = 0.SI<MeterPerSquareSecond>(); - switch (driverBehavior) { - case DrivingBehavior.Accelerating: - acc = 1.SI<MeterPerSquareSecond>(); - break; - case DrivingBehavior.Braking: - acc = -1.SI<MeterPerSquareSecond>(); - break; - case DrivingBehavior.Halted: - acc = 0.SI<MeterPerSquareSecond>(); - break; - default: - throw new ArgumentOutOfRangeException(); - } - - - - - - vehicleContainer.Setup(v => v.DriverInfo.DriverAcceleration).Returns(acc); - gearboxData = new GearboxData(); - return vehicleContainer; - } - - private IEngineInfo GetEngineInfo(Mock<IVehicleContainer> vehicleContainer, VectoRunData runData) - { - //EngineInfo - var engineInfo = new Mock<IEngineInfo>(); - vehicleContainer.Setup(c => c.EngineInfo).Returns(engineInfo.Object); - engineInfo.Setup(e => e.EngineIdleSpeed).Returns(runData.EngineData.IdleSpeed); - engineInfo.Setup(e => e.EngineRatedSpeed).Returns(runData.EngineData.FullLoadCurves.First().Value.RatedSpeed); - - engineInfo.Setup(e => e.EngineSpeed).Returns(1400.RPMtoRad()); - engineInfo.Setup(e => e.EngineN95hSpeed).Returns - (runData.EngineData.FullLoadCurves.First().Value.N95hSpeed); - engineInfo.Setup(e => e.EngineN80hSpeed).Returns( - runData.EngineData.FullLoadCurves.First().Value.N80hSpeed); - engineInfo.Setup(e => e.EngineStationaryFullPower(It.IsAny<PerSecond>())).Returns((PerSecond n) => - runData.EngineData.FullLoadCurves[0].FullLoadStationaryPower(n)); - return engineInfo.Object; - } - - private CycleData GetCycleData() - { - return new CycleData() { - LeftSample = new DrivingCycleData.DrivingCycleEntry() { - PTOActive = PTOActivity.Inactive, - VehicleTargetSpeed = 10.KMPHtoMeterPerSecond() - } - }; - } - - private Mock<IVehicleInfo> GetVehicleInfo(MeterPerSecond speed) - { - var vehicleInfo = new Mock<IVehicleInfo>(); - vehicleInfo.Setup(v => v.VehicleSpeed).Returns(speed); - vehicleInfo.Setup(v => v.AirDragResistance(It.IsAny<MeterPerSecond>(), It.IsAny<MeterPerSecond>())) - .Returns(0.SI<Newton>()); - vehicleInfo.Setup(v => v.RollingResistance(It.IsAny<Radian>())).Returns(0.SI<Newton>()); - vehicleInfo.Setup(v => v.SlopeResistance(It.IsAny<Radian>())).Returns(0.SI<Newton>()); - vehicleInfo.Setup(v => v.TotalMass).Returns(12000.SI<Kilogram>()); - return vehicleInfo; - } - - private Mock<ITestPowertrain> GetMockTestPowertrain(VectoRunData runData, - out Mock<ISimpleVehicleContainer> simpleContainer) - { - var testPt = new Mock<ITestPowertrain>(); - simpleContainer = GetSimplePowertrain(runData, - out var testGearbox); - - - - testPt.Setup(t => t.Container).Returns(simpleContainer.Object); - testPt.Setup(t => t.Gearbox).Returns(testGearbox.Object); - - //Vehicle - var vehicle = new Mock<ITestPowertrainVehicle>(); - vehicle.Setup(v => v.Initialize( - It.IsAny<MeterPerSecond>(), - It.IsAny<Radian>())).Returns(new ResponseSuccess(this)); - testPt.Setup(t => t.Vehicle).Returns(vehicle.Object); - - - return testPt; - } - - private Mock<IVehicleDeclarationInputData> GetMockInputData(double[]? gearRatios) - { - var input = new Mock<IVehicleDeclarationInputData>(); - var components = new Mock<IVehicleComponentsDeclaration>(); - input.Setup(i => i.Components).Returns(components.Object); - var gbx = new Mock<IGearboxDeclarationInputData>(); - var tc = new Mock<ITorqueConverterDeclarationInputData>(); - - components.Setup(c => c.GearboxInputData).Returns(gbx.Object); - components.Setup(c => c.TorqueConverterInputData).Returns(tc.Object); - gearRatios = gearRatios ?? new double[] { }; - var header = "Input Speed [rpm],Input Torque [Nm],Torque Loss [Nm]"; - var efficiency = 0.98; - var data = new List<string>(); - - foreach (var speed in new[] { 0, 10000 }) { - foreach (var tq in new[] { 1e5, -1e5, 0 }) { - data.Add(FormattableString.Invariant($"{speed:f2}, {tq:f2}, {(1 - efficiency) * Math.Abs(tq)}")); - } - } - - var lossmap = InputDataHelper.InputDataAsTableData(header, data.ToArray()); - //lossmap.Columns - var gears = gearRatios.Select((x, idx) => { - var gear = new Mock<ITransmissionInputData>(); - gear.Setup(g => g.Ratio).Returns(x); - gear.Setup(g => g.Gear).Returns(idx + 1); - //gear.Setup(g => g.Efficiency).Returns(0.98); - gear.Setup(g => g.LossMap).Returns(lossmap); - gear.Setup(g => g.MaxInputSpeed).Returns(2000.RPMtoRad()); - return gear.Object; - }).ToList(); - gbx.Setup(g => g.Type).Returns(GearboxType.ATSerial); - gbx.Setup(g => g.Gears).Returns(gears); - - var tcData = InputDataHelper.InputDataAsTableData(TcHeader, TcData); - tc.Setup(t => t.TCData).Returns(tcData); - return input; - } - - private static VectoRunData GetDummyVectoRunData(IVehicleDeclarationInputData inputData) - { - var nrOfGears = inputData.Components.GearboxInputData.Gears.Count; - var fldData = InputDataHelper.InputDataAsTableData(EngineFldHeader, EngineFldData); - var fld = FullLoadCurveReader.Create(fldData); - - // create gearbox data - var tcDataAdapter = new TorqueConverterDataAdapter(); - - // fuel data - var fuelData = new CombustionEngineFuelData() { - ConsumptionMap = FuelConsumptionMapReader.Create( - InputDataHelper.InputDataAsTableData( - "engine speed [rpm] ,torque [Nm] ,fuel consumption [g/h] ,whr power electrical [W]", - "500,-131,0,0", - "500,95.6,1814.959,0", - "500,573.6,9771.095,0", - "2453,-209.12,0,0", - "2453,764.8,39097.94,0" - )), - FuelData = DeclarationData.FuelData.Lookup(FuelType.DieselCI), - }; - - var runData = new VectoRunData() { - VehicleData = new VehicleData() { - DynamicTyreRadius = 0.465.SI<Meter>(), - GrossVehicleMass = 12_000.SI<Kilogram>(), - CurbMass = 10_000.SI<Kilogram>(), - }, - EngineData = new CombustionEngineData() { - Inertia = 0.SI<KilogramSquareMeter>(), - FullLoadCurves = new Dictionary<uint, EngineFullLoadCurve>(), - IdleSpeed = 600.RPMtoRad(), - RatedSpeedDeclared = 2000.RPMtoRad(), - Fuels = new List<CombustionEngineFuelData>() { - fuelData, - } - }, - Cycle = new DrivingCycleData() { - CycleType = CycleType.DistanceBased - } - }; - for (uint i = 0; i <= nrOfGears; i++) { - runData.EngineData.FullLoadCurves[i] = fld; - } - - var gbxDataAdapter = new GearboxDataAdapter(tcDataAdapter); - var gbxTypes = new[] { - GearboxType.ATSerial, GearboxType.ATPowerSplit - }; - - var gearboxData = gbxDataAdapter.CreateGearboxData(inputData, runData, - new ATShiftStrategyOptimizedPolygonCalculator(), new GearboxType[] { - GearboxType.ATSerial, - GearboxType.ATPowerSplit - }); - - var gearShiftParams = - gbxDataAdapter.CreateGearshiftData(1.0, runData.EngineData.IdleSpeed, GearboxType.ATSerial, nrOfGears); - - runData.GearboxData = gearboxData; - runData.GearshiftParameters = gearShiftParams; - return runData; - } - - private Mock<ISimpleVehicleContainer> GetSimplePowertrain(VectoRunData runData, - out Mock<ITestPowertrainTransmission> testGearbox) - { - var simplePt = new Mock<ISimpleVehicleContainer>(); - - testGearbox = GetMockTestGearbox(runData.GearboxData.Gears); - - - simplePt.Setup(s => s.GearboxInfo).Returns(testGearbox.Object); - simplePt.Setup(s => s.GearboxOutPort).Returns(testGearbox.Object); - - - - - //VehiclePort - return simplePt; - } - - private Mock<ITestPowertrainTransmission> GetMockTestGearbox(Dictionary<uint, GearData> ratios) - { - Mock<IAPTGearbox> amtGearbox = new Mock<IAPTGearbox>(); - amtGearbox.Name = "APT_TestGearbox"; - Mock<ITestPowertrainTransmission> gbx = amtGearbox.As<ITestPowertrainTransmission>(); - - - - gbx.Setup(g => g.LastUpshift).Returns(-double.MaxValue.SI<Second>()); - gbx.Setup(g => g.LastDownshift).Returns(-double.MaxValue.SI<Second>()); - - GearshiftPosition gear = null; - gbx.SetupGet(g => g.Gear).Returns(() => { return gear; }); - gbx.SetupSet(g => g.SetGear = It.IsAny<GearshiftPosition>()) - .Callback<GearshiftPosition>(p => { gear = p; }); - - - GearshiftPosition nextGear = null; - gbx.SetupGet(g => g.NextGear).Returns(() => nextGear); - gbx.SetupSet(g => g.SetNextGear = It.IsAny<GearshiftPosition>()) - .Callback<GearshiftPosition>(p => nextGear = p); - - gbx.Setup(p => p.Initialize(It.IsAny<NewtonMeter>(), - It.IsAny<PerSecond>())).Returns((NewtonMeter tq, PerSecond rpm) => { - return new ResponseSuccess(this) { - Engine = { - EngineSpeed = rpm, - PowerRequest = tq * rpm, - }, - }; - }); - gbx.Setup(p => p.Request( - It.IsAny<Second>(), - It.IsAny<Second>(), - It.IsAny<NewtonMeter>(), - It.IsAny<PerSecond>(), - true)).Returns(( - Second absTime, - Second dt, - NewtonMeter t, - PerSecond n, - bool dryRun) => { - - var ratio = - gbx.Object.Gear == null ? 1.0 : ratios[gbx.Object.Gear.Gear].Ratio; - return dryRun - ? new ResponseDryRun(this) { - Engine = { - PowerRequest = n * t, EngineSpeed = n * ratio, - DynamicFullLoadPower = (t / ratio + 2300.SI<NewtonMeter>()) * n * ratio, - TotalTorqueDemand = t, - TorqueOutDemand = t, - }, - Clutch = { PowerRequest = n * t }, - DeltaFullLoad = n * t / 2 * (-1) - } - : new ResponseSuccess(this) { - Engine = { - PowerRequest = n * t, - EngineSpeed = n * ratio - - }, - Clutch = { PowerRequest = n * t } - }; - }); - return gbx; - } - - private static PerSecond GetAngularVelocityBySpeed(double speedKmh, VectoRunData runData) - { - // r_dyn = 0.465m, i_axle = 6.2 - var angularVelocity = - speedKmh.KMPHtoMeterPerSecond() - / runData.VehicleData.DynamicTyreRadius * 6.2; - return angularVelocity; - } - - - - - - - public const string TcHeader = "Speed Ratio, Torque Ratio,MP1000"; - - public static readonly string[] TcData = new[] { - "0.0,1.80,377.80", - "0.1,1.71,365.21", - "0.2,1.61,352.62", - "0.3,1.52,340.02", - "0.4,1.42,327.43", - "0.5,1.33,314.84", - "0.6,1.23,302.24", - "0.7,1.14,264.46", - "0.8,1.04,226.68", - "0.9,1.02,188.90", - "1.0,1.0,0.00", - "1.100,0.999,-40.34", - "1.222,0.998,-80.34", - "1.375,0.997,-136.11", - "1.571,0.996,-216.52", - "1.833,0.995,-335.19", - "2.200,0.994,-528.77", - "2.750,0.993,-883.40", - "4.400,0.992,-2462.17", - "11.000,0.991,-16540.98", - }; - - public const string EngineFldHeader = "engine speed [1/min],full load torque [Nm],motoring torque [Nm],PT1 [s]"; - - public static readonly string[] EngineFldData = new[] { - "560,1180,-149,0.6", - "600,1282,-148,0.6", - "799.9999999,1791,-149,0.6", - "1000,2300,-160,0.6", - "1200,2300,-179,0.6", - "1400,2300,-203,0.6", - "1599.999999,2079,-235,0.49", - "1800,1857,-264,0.25", - "2000.000001,1352,-301,0.25", - "2100,1100,-320,0.25", - }; [TestCase(1, 1, 1000, 1500, 0, Description = "Engage 0-> 1C")] public void Gearbox_Engage(int gear, int newGear, double tqNm, double nRPM, double speedKmh) { var gearRatios = new[] { 6.38, 4.63, 3.44, 2.59, 1.86, 1.35, 1, 0.76 }; - + var vehicleContainer = GetMockVehicleContainer(speedKmh, DrivingBehavior.Accelerating, gearRatios, inputData: out _, - runData: out var runData, - gearboxData: out _, simplePt: out _); - + runData: out var runData, simplePt: out _); + var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData: runData); - - var response = gbx.Initialize(0.SI<NewtonMeter>(), angularVelocity); - - - + + + var absTime = 0.SI<Second>(); var dt = 2.SI<Second>(); - - + + var expectedN = nRPM.RPMtoRad(); angularVelocity = expectedN / gearRatios[gear]; - - - gbx.CurrentState = new ATGearboxState() - { - Gear = gbx.Gear, - }; - + + var initGear = shiftStrategy.InitGear(absTime, dt, 0.SI<NewtonMeter>(), angularVelocity); + SetCurrentGear(gbx, initGear); + var expectedT = tqNm.SI<NewtonMeter>(); var torque = expectedT * gearRatios[gear]; - + var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, torque, angularVelocity, expectedT, expectedN, new GearshiftPosition((uint)gear), -double.MaxValue.SI<Second>(), new ResponseSuccess(this)); - + Assert.AreEqual(newGear, shiftStrategy.NextGear.Gear); - + var shiftExpected = gear != newGear; //Different Gear - shiftExpected = shiftRequired || gbx.Disengaged; //Gearbox was disengaged - + var disengaged = gbx.Object.Disengaged; + shiftExpected = shiftRequired || disengaged; //Gearbox was disengaged + Assert.AreEqual(shiftExpected, shiftRequired); } [TestCase(2, 1, -1000, 1500, 4, DrivingBehavior.Braking, Description = "_ -> 0: disengage before halting")] public void Gearbox_Disengange(int gear, int newGear, double tqNm, double nRPM, double speedKmh, DrivingBehavior driverBehavior) - { - var gearRatios = new[] { 6.38, 4.63, 3.44, 2.59, 1.86, 1.35, 1, 0.76 }; - - var vehicleContainer = GetMockVehicleContainer(speedKmh, - driverBehavior, - gearRatios, - out var inputData, - out var runData, - out var gearboxData, out _); - + { + // Assert.Ignore("Work in Progress"); + var gearRatios = new[] { 6.38, 4.63, 3.44, 2.59, 1.86, 1.35, 1, 0.76 }; + + var vehicleContainer = GetMockVehicleContainer(speedKmh, driverBehavior, gearRatios, + inputData: out _, + runData: out var runData, simplePt: out _); + var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); - - gbx.Initialize(0.SI<NewtonMeter>(), angularVelocity); - - + var absTime = 0.SI<Second>(); var dt = 2.SI<Second>(); - - + + var initGear = shiftStrategy.InitGear(absTime, dt, 0.SI<NewtonMeter>(), angularVelocity); + SetCurrentGear(gbx, initGear); + var expectedN = nRPM.RPMtoRad(); angularVelocity = expectedN / gearRatios[gear]; - + //Called in gbx initialize //var gearShiftPosition = shiftStrategy.InitGear(absTime, Constants.SimulationSettings.TargetTimeInterval, 1.SI<NewtonMeter>(), // angularVelocity); var engagedPosition = shiftStrategy.Engage(absTime, dt, null, null); - - Assert.IsTrue(engagedPosition.Engaged); - - gbx.CurrentState = new ATGearboxState() - { - Disengaged = gbx.Disengaged, - Gear = gbx.Gear, - }; - + + // gbx.CurrentState = new ATGearboxState() + // { + // Disengaged = gbx.Disengaged, + // Gear = gbx.Gear, + // }; + var expectedT = tqNm.SI<NewtonMeter>(); var torque = expectedT * gearRatios[gear]; - - + + var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, torque, angularVelocity, expectedT, expectedN, new GearshiftPosition((uint)gear), -double.MaxValue.SI<Second>(), new ResponseSuccess(this)); - + Assert.AreEqual(newGear, shiftStrategy.NextGear.Gear); - + var shiftExpected = gear != newGear; //Different Gear - shiftExpected = shiftRequired || gbx.Disengaged; //Gearbox was disengaged - + var disengaged = false; + shiftExpected = shiftRequired || disengaged; //Gearbox was disengaged + Assert.AreEqual(shiftExpected, shiftRequired); } @@ -565,64 +174,250 @@ public class ATShiftStrategyOptimizedTests [TestCase(1, false, 1, true, 100, 500, 1, Description = "EarlyUpshift-TC", TestName="EarlyUpshift-TC")] public void Gearbox_Upshift(int gear, bool tcLocked, int newGear, bool newTcLocked, double tqNm, double nRPM, double speedKmh) { + // Assert.Ignore("Work in Progress"); var gearRatios = new[] { 3.4, 1.9, 1.42, 1.0, 0.7, 0.62 }; - + var vehicleContainer = GetMockVehicleContainer( speedKmh, DrivingBehavior.Accelerating, gearRatios, - out var inputData, out var runData, out var gearboxData, out var simplePt); - - + out var inputData, out var runData, out var simplePt); + + + var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); - var gbxResponse = gbx.Initialize(0.SI<NewtonMeter>(), angularVelocity); - - Assert.AreEqual((uint)gear, gbx.Gear.Gear); - Assert.That(gbx.Gear.TorqueConverterLocked, Is.EqualTo(tcLocked)); - - - var absTime = 0.SI<Second>(); - var dt = 2.SI<Second>(); - - gbx.CurrentState = new ATGearboxState() - { - Disengaged = gbx.Disengaged, - Gear = gbx.Gear, - }; - + var absTime = 0.SI<Second>(); + var dt = 2.SI<Second>(); + + var gbxObj = gbx.Object; + // var gbxResponse = gbx.Object.Initialize(0.SI<NewtonMeter>(), angularVelocity); + var initGear = shiftStrategy.InitGear(absTime, dt, 0.SI<NewtonMeter>(), angularVelocity); + + + Assert.AreEqual((uint)gear, initGear.Gear); + Assert.That(initGear.TorqueConverterLocked, Is.EqualTo(tcLocked)); + + SetCurrentGear(gbx, initGear); + + + // gbx.CurrentState = new ATGearboxState() + // { + // Disengaged = gbx.Disengaged, + // Gear = gbx.Gear, + // }; + + var inAngularVelocity = nRPM.RPMtoRad(); var outAngularVelocity = inAngularVelocity / gearRatios[gear]; - + var inTorque = tqNm.SI<NewtonMeter>(); var outTortque = inTorque * gearRatios[gear]; - + var response = new ResponseSuccess(this); response.Engine.DynamicFullLoadTorque = 50.SI<NewtonMeter>(); response.Engine.EngineSpeed = inAngularVelocity; response.Engine.TorqueOutDemand = inTorque; - - + + runData.GearshiftParameters.RatingFactorCurrentGear = 1.1; + + + var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, outTortque, outAngularVelocity, inTorque, inAngularVelocity, initGear, -double.MaxValue.SI<Second>(), response); + + + Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(newGear)); + Assert.That(shiftStrategy.NextGear.TorqueConverterLocked ?? true, Is.EqualTo(newTcLocked)); + + var shiftExpected = gear != newGear; //Different Gear + + shiftExpected = shiftRequired || gbx.Object.Disengaged; //Gearbox was disengaged + + Assert.AreEqual(shiftExpected, shiftRequired); + } + private void SetCurrentGear(Mock<IAPTGearbox> gbx, GearshiftPosition initGear) + { + gbx.Setup(g => g.Gear).Returns(initGear); + gbx.SetupGet(g => g.TorqueConverterLocked).Returns(initGear.TorqueConverterLocked ?? false); + } - var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, outTortque, outAngularVelocity, inTorque, inAngularVelocity, gbx.Gear, -double.MaxValue.SI<Second>(), response); - + [TestCase(2, true, 3, true, 100, 1800, 13, Description = "Upshift-TCLocked")] + [TestCase(1, false, 1, true, 100, 1000, 1, Description = "Upshift-TC")] + public void Gearbox_EarlyUpshift(int gear, bool tcLocked, int newGear, bool newTcLocked, double tqNm, double nRPM, double speedKmh) + { + var gearRatios = new[] { 3.4, 1.9, 1.42, 1.0, 0.7, 0.62 }; + + var vehicleContainer = GetMockVehicleContainer( + speedKmh, + DrivingBehavior.Accelerating, + gearRatios, + out var inputData, out var runData, out _); + + + var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); + var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); + + var absTime = 0.SI<Second>(); + var dt = 2.SI<Second>(); + var initGear = shiftStrategy.InitGear(absTime, dt, 0.SI<NewtonMeter>(), angularVelocity); + SetCurrentGear(gbx, initGear); + + Assert.AreEqual((uint)gear, initGear.Gear); + Assert.That(initGear.TorqueConverterLocked, Is.EqualTo(tcLocked)); + + + + var inAngularVelocity = nRPM.RPMtoRad(); + var outAngularVelocity = inAngularVelocity / gearRatios[gear]; + + var inTorque = tqNm.SI<NewtonMeter>(); + var outTortque = inTorque * gearRatios[gear]; + + var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, outTortque, outAngularVelocity, inTorque, inAngularVelocity, initGear, -double.MaxValue.SI<Second>(), new ResponseSuccess(this)); + + Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(newGear)); Assert.That(shiftStrategy.NextGear.TorqueConverterLocked ?? true, Is.EqualTo(newTcLocked)); + + var shiftExpected = gear != newGear; //Different Gear + shiftExpected = shiftRequired || gbx.Object.Disengaged; //Gearbox was disengaged + + Assert.AreEqual(shiftExpected, shiftRequired); + } - var shiftExpected = gear != newGear; //Different Gear - shiftExpected = shiftRequired || gbx.Disengaged; //Gearbox was disengaged +// + [TestCase(1, false, 2, false, 100, 1000, 1, Description = "Upshift-TC")] + public void Gearbox_Upshift_TC_TC(int gear, bool tcLocked, int newGear, bool newTcLocked, double tqNm, double nRPM, double speedKmh) + { + var gearRatios = new[] { 3.4, 1.3, 1.1, 1.0, 0.7, 0.62 }; + + var vehicleContainer = GetMockVehicleContainer( + speedKmh, + DrivingBehavior.Accelerating, + gearRatios, + out var inputData, out var runData, out _); + + + var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); + var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); + + + var absTime = 0.SI<Second>(); + var dt = 2.SI<Second>(); + + Assert.That(runData.GearboxData.GearList.First(p => p.Gear == 2).TorqueConverterLocked, Is.False, "Expected 2nd gear with TC"); + var initGear = shiftStrategy.InitGear(absTime, dt, 0.SI<NewtonMeter>(), angularVelocity); + SetCurrentGear(gbx, initGear); + + + var inAngularVelocity = nRPM.RPMtoRad(); + var outAngularVelocity = inAngularVelocity / gearRatios[gear]; + + var inTorque = tqNm.SI<NewtonMeter>(); + var outTortque = inTorque * gearRatios[gear]; + + var response = new ResponseSuccess(this); + response.Engine.EngineSpeed = inAngularVelocity; + response.Engine.TorqueOutDemand = inTorque; + + + var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, outTortque, outAngularVelocity, inTorque, inAngularVelocity, initGear, -double.MaxValue.SI<Second>(), response); + + + Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(newGear)); + Assert.That(shiftStrategy.NextGear.TorqueConverterLocked ?? true, Is.EqualTo(newTcLocked)); + + var shiftExpected = gear != newGear; //Different Gear + shiftExpected = shiftRequired || gbx.Object.Disengaged; //Gearbox was disengaged + Assert.AreEqual(shiftExpected, shiftRequired); } +// +// +// +// + [TestCase(3, true, 2, true, 900, 600, 15, Description = "Downshift", TestName="Gearbox_DownShift_1")] + public void Gearbox_Downshift(int gear, bool tcLocked, int newGear, bool newTcLocked, double tqNm, double nRPM, double speedKmh) + { + // Assert.Ignore("Work in Progress"); + + var gearRatios = new[] { 3.4, 1.9, 1.42, 1.0, 0.7, 0.62 }; + + var vehicleContainer = GetMockVehicleContainer( + speedKmh, + DrivingBehavior.Accelerating, + gearRatios, + out var inputData, + out var runData, + out var simplePt); + + vehicleContainer.Setup(v => v.DriverInfo.DrivingAction).Returns(DrivingAction.Accelerate); + + var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); + var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); + + + var absTime = 0.SI<Second>(); + var dt = 2.SI<Second>(); + + var initGear = shiftStrategy.InitGear(absTime, dt, 0.SI<NewtonMeter>(), angularVelocity); + + Assert.AreEqual((uint)gear, initGear.Gear); + Assert.That(initGear.TorqueConverterLocked, Is.EqualTo(tcLocked)); + + - [TestCase(2, true, 3, true, 100, 1800, 13, Description = "Upshift-TCLocked")] - [TestCase(1, false, 1, true, 100, 1000, 1, Description = "Upshift-TC")] - public void Gearbox_EarlyUpshift(int gear, bool tcLocked, int newGear, bool newTcLocked, double tqNm, double nRPM, double speedKmh) + + var inAngularVelocity = nRPM.RPMtoRad(); + var outAngularVelocity = inAngularVelocity / gearRatios[gear]; + + var inTorque = tqNm.SI<NewtonMeter>(); + var outTortque = inTorque * gearRatios[gear]; + + var response = new ResponseSuccess(this); + response.Engine.EngineSpeed = inAngularVelocity; + response.Engine.TorqueOutDemand = inTorque; + + + var mockPort = new Mock<ITnOutPort>(); + + simplePt.Setup(s => s.GearboxOutPort).Returns(mockPort.Object); + mockPort.Setup(p => p.Request( + It.IsAny<Second>(), + It.IsAny<Second>(), + It.IsAny<NewtonMeter>(), + It.IsAny<PerSecond>(), + true + )).Returns((Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, bool dryRun) => { + var response = new ResponseDryRun(this); + response.Engine.PowerRequest = outTorque * outAngularVelocity; + return response; + }); + // + // + // + // + // var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, outTortque, outAngularVelocity, inTorque, inAngularVelocity, gbx.Gear, -double.MaxValue.SI<Second>(), response); + // + // + // Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(newGear)); + // Assert.That(shiftStrategy.NextGear.TorqueConverterLocked ?? true, Is.EqualTo(newTcLocked)); + // + // var shiftExpected = gear != newGear; //Different Gear + // var disengaged = false; //gbx.Disengaged; + // shiftExpected = shiftRequired || disengaged; //Gearbox was disengaged + // + // Assert.AreEqual(shiftExpected, shiftRequired); + } +// + [TestCase(3, true, 2, true, 200, 700, 15, Description = "Downshift_3", TestName = "Gearbox_DownShift_3")] + public void Gearbox_Downshift_2(int gear, bool tcLocked, int newGear, bool newTcLocked, double tqNm, double nRPM, + double speedKmh) { var gearRatios = new[] { 3.4, 1.9, 1.42, 1.0, 0.7, 0.62 }; @@ -630,813 +425,638 @@ public class ATShiftStrategyOptimizedTests speedKmh, DrivingBehavior.Accelerating, gearRatios, - out var inputData, out var runData, out var gearboxData, out _); + out var inputData, + out var runData, + out var simplePt); + vehicleContainer.Setup(v => v.DriverInfo.DrivingAction).Returns(DrivingAction.Accelerate); - var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); - var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); + // Condition from ATShiftStrategy + //if (DataBus.VehicleInfo.VehicleSpeed < DataBus.DrivingCycleInfo.CycleData.LeftSample.VehicleTargetSpeed - 10.KMPHtoMeterPerSecond() && + // DataBus.DriverInfo.DriverAcceleration < 0.SI<MeterPerSquareSecond>()) + vehicleContainer.Setup(v => v.DrivingCycleInfo.CycleData).Returns(new CycleData() { + LeftSample = new DrivingCycleData.DrivingCycleEntry() { + VehicleTargetSpeed = 30.KMPHtoMeterPerSecond() + } + }); + + vehicleContainer.Setup(v => v.DriverInfo.DriverAcceleration).Returns(-0.1.SI<MeterPerSquareSecond>()); - var response = gbx.Initialize(0.SI<NewtonMeter>(), angularVelocity); - Assert.AreEqual((uint)gear, gbx.Gear.Gear); - Assert.That(gbx.Gear.TorqueConverterLocked, Is.EqualTo(tcLocked)); + runData.EngineData.Inertia = 1.SI<KilogramSquareMeter>(); + var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx, out var gbxNextComponent); + + var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); + var absTime = 0.SI<Second>(); var dt = 2.SI<Second>(); + var initGear = shiftStrategy.InitGear(absTime, dt, 0.SI<NewtonMeter>(), angularVelocity); + SetCurrentGear(gbx, initGear); - gbx.CurrentState = new ATGearboxState() - { - Disengaged = gbx.Disengaged, - Gear = gbx.Gear, - }; + + Assert.AreEqual((uint)gear, initGear.Gear); + Assert.That(initGear.TorqueConverterLocked, Is.EqualTo(tcLocked)); + + var dryRunResponse = new ResponseDryRun(this); + dryRunResponse.Engine.EngineSpeed = + vehicleContainer.Object.EngineInfo.EngineN95hSpeed - 1.SI<PerSecond>(); + dryRunResponse.DeltaFullLoad = 40_000.SI<Watt>(); + + // gbx.Setup(g => g) + var testPt = + vehicleContainer.Object.SimplePowertrainBuilder.CreateTestPowertrain(vehicleContainer.Object, false); + + var mockGb = Mock.Get(testPt.Gearbox); + mockGb.Setup(g => g.Request(It.IsAny<Second>(), It.IsAny<Second>(), It.IsAny<NewtonMeter>(), + It.IsAny<PerSecond>(), true)).Returns(dryRunResponse); + + + var inAngularVelocity = nRPM.RPMtoRad(); + var outAngularVelocity = inAngularVelocity / gearRatios[gear]; - var inAngularVelocity = nRPM.RPMtoRad(); - var outAngularVelocity = inAngularVelocity / gearRatios[gear]; + var inTorque = tqNm.SI<NewtonMeter>(); + var outTortque = inTorque * gearRatios[gear]; + + var shiftRequired = shiftStrategy.ShiftRequired(absTime, + dt, + outTortque, outAngularVelocity, inTorque, inAngularVelocity, initGear, -double.MaxValue.SI<Second>(), new ResponseSuccess(this)); + + + Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(newGear)); + Assert.That(shiftStrategy.NextGear.TorqueConverterLocked ?? true, Is.EqualTo(newTcLocked)); + + var shiftExpected = gear != newGear; //Different Gear + shiftExpected = shiftRequired || gbx.Object.Disengaged; //Gearbox was disengaged + + Assert.AreEqual(shiftExpected, shiftRequired); + } + + // [TestCase(3, true, 2, true, 1700, 700, 15, Description = "Downshift", TestName = "Gearbox_Early_DownShift_1")] + [TestCase(6, true, 5, true, -100, 700, 45, Description = "Downshift", TestName = "Gearbox_Early_DownShift_1")] + public void Gearbox_Early_Downshift(int gear, bool tcLocked, int newGear, bool newTcLocked, double tqNm, double nRPM, double speedKmh) + { + var gearRatios = new[] { 3.4, 1.9, 1.42, 1.0, 0.7, 0.62 }; + + var vehicleContainer = GetMockVehicleContainer( + speedKmh, + DrivingBehavior.Accelerating, + gearRatios, + out var inputData, out var runData, out var simplePt); + + vehicleContainer.Setup(v => v.DriverInfo.DrivingAction).Returns(DrivingAction.Accelerate); + + var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); + var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); + + + + var absTime = 0.SI<Second>(); + var dt = 2.SI<Second>(); + var initGear = shiftStrategy.InitGear(absTime, dt, 0.SI<NewtonMeter>(), angularVelocity); + SetCurrentGear(gbx, initGear); + + Assert.AreEqual((uint)gear, initGear.Gear); + Assert.That(initGear.TorqueConverterLocked, Is.EqualTo(tcLocked)); + var gearIdx = gear - 1; + var inAngularVelocity = nRPM.RPMtoRad(); + var outAngularVelocity = inAngularVelocity / gearRatios[gearIdx]; + var inTorque = tqNm.SI<NewtonMeter>(); - var outTortque = inTorque * gearRatios[gear]; + var outTortque = inTorque * gearRatios[gearIdx]; + + var response = new ResponseSuccess(this); + response.Engine.EngineSpeed = inAngularVelocity; + response.Engine.TorqueOutDemand = inTorque; + + + var mockPort = new Mock<ITnOutPort>(); + + // simplePt.Setup(s => s.GearboxOutPort).Returns(mockPort.Object); + // mockPort.Setup(p => p.Request( + // It.IsAny<Second>(), + // It.IsAny<Second>(), + // It.IsAny<NewtonMeter>(), + // It.IsAny<PerSecond>(), + // true + // )).Returns((Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, bool dryRun) => { + // var response = new ResponseDryRun(this); + // response.Engine.PowerRequest = outTorque * outAngularVelocity; + // return response; + // }); + + + runData.GearshiftParameters.RatingFactorCurrentGear = 2; + + var shiftRequired = shiftStrategy.ShiftRequired(absTime, + dt, + outTortque, + outAngularVelocity, + inTorque, + inAngularVelocity, + initGear, -double.MaxValue.SI<Second>(), response); + + + Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(newGear)); + Assert.That(shiftStrategy.NextGear.TorqueConverterLocked ?? true, Is.EqualTo(newTcLocked)); + + var shiftExpected = gear != newGear; //Different Gear + shiftRequired = shiftRequired || gbx.Object.Disengaged; //Gearbox was disengaged + + Assert.AreEqual(shiftExpected, shiftRequired); + } + + private Mock<IVehicleContainer> GetMockVehicleContainer(double speedKmh, DrivingBehavior driverBehavior, + double[] gearRatios, + out Mock<IVehicleDeclarationInputData> inputData, out VectoRunData runData, + out Mock<ISimpleVehicleContainer> simplePt) + { + var vehicleContainer = new Mock<IVehicleContainer>(); - var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, outTortque, outAngularVelocity, inTorque, inAngularVelocity, gbx.Gear, -double.MaxValue.SI<Second>(), new ResponseSuccess(this)); + inputData = GetMockInputData(gearRatios); + runData = GetDummyVectoRunData(inputData.Object); + + vehicleContainer.Setup(c => c.RunData).Returns(runData); + + //Testpowertrain + var testPowertrain = GetMockTestPowertrain( + runData, + out simplePt); - Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(newGear)); - Assert.That(shiftStrategy.NextGear.TorqueConverterLocked ?? true, Is.EqualTo(newTcLocked)); + vehicleContainer.Setup(c => c.SimplePowertrainBuilder.CreateTestPowertrain(It.IsAny<IVehicleContainer>(), + It.IsAny<bool>())).Returns(testPowertrain.Object); - var shiftExpected = gear != newGear; //Different Gear - shiftExpected = shiftRequired || gbx.Disengaged; //Gearbox was disengaged + //VehicleInfo + vehicleContainer.Setup(c => c.VehicleInfo) + .Returns(GetVehicleInfo(speedKmh.KMPHtoMeterPerSecond()).Object); - Assert.AreEqual(shiftExpected, shiftRequired); - } + //EngineInfo + vehicleContainer.Setup(c => c.EngineInfo).Returns(GetEngineInfo(vehicleContainer, runData)); + + //AxleGearInfo + var axleGearInfo = new Mock<IAxlegearInfo>(); + vehicleContainer.Setup(c => c.AxlegearInfo).Returns(axleGearInfo.Object); + axleGearInfo.Setup(a => a.AxlegearLoss()).Returns(0.SI<Watt>()); -// - [TestCase(1, false, 2, false, 100, 1000, 1, Description = "Upshift-TC")] - public void Gearbox_Upshift_TC_TC(int gear, bool tcLocked, int newGear, bool newTcLocked, double tqNm, double nRPM, double speedKmh) - { - var gearRatios = new[] { 3.4, 1.3, 1.1, 1.0, 0.7, 0.62 }; + //WheelsInfo + var wi = new Mock<IWheelsInfo>(); + vehicleContainer.Setup(c => c.WheelsInfo).Returns(wi.Object); + wi.Setup(w => w.ReducedMassWheels).Returns(0.SI<Kilogram>()); - var vehicleContainer = GetMockVehicleContainer( - speedKmh, - DrivingBehavior.Accelerating, - gearRatios, - out var inputData, out var runData, out var gearboxData, out _); + //Cycle Info + var cycleInfo = new Mock<IDrivingCycleInfo>(); + vehicleContainer.Setup(c => c.DrivingCycleInfo).Returns(cycleInfo.Object); + cycleInfo.Setup(c => c.CycleData).Returns( + GetCycleData()); + cycleInfo.Setup(c => c.RoadGradient).Returns(0.SI<Radian>()); - var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); - var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); + cycleInfo.Setup(c => c.CycleLookAhead(It.IsAny<Meter>())).Returns(new DrivingCycleData.DrivingCycleEntry() { + Altitude = 0.SI<Meter>() + }); + cycleInfo.Setup(c => c.Altitude).Returns(0.SI<Meter>()); - var gbxResponse = gbx.Initialize(0.SI<NewtonMeter>(), angularVelocity); + //DriverINfo + vehicleContainer.Setup(v => v.DriverInfo.DriverBehavior).Returns(driverBehavior); + var acc = 0.SI<MeterPerSquareSecond>(); + switch (driverBehavior) { + case DrivingBehavior.Accelerating: + acc = 1.SI<MeterPerSquareSecond>(); + break; + case DrivingBehavior.Braking: + acc = -1.SI<MeterPerSquareSecond>(); + break; + case DrivingBehavior.Halted: + acc = 0.SI<MeterPerSquareSecond>(); + break; + default: + throw new ArgumentOutOfRangeException(); + } - Assert.AreEqual((uint)gear, gbx.Gear.Gear); - Assert.That(gbx.Gear.TorqueConverterLocked, Is.EqualTo(tcLocked)); - var absTime = 0.SI<Second>(); - var dt = 2.SI<Second>(); - gbx.CurrentState = new ATGearboxState() - { - Disengaged = gbx.Disengaged, - Gear = gbx.Gear, - }; - Assert.That(gbx.ModelData.GearList.First(p => p.Gear == 2).TorqueConverterLocked, Is.False, "Expected 2nd gear with TC"); - var inAngularVelocity = nRPM.RPMtoRad(); - var outAngularVelocity = inAngularVelocity / gearRatios[gear]; + vehicleContainer.Setup(v => v.DriverInfo.DriverAcceleration).Returns(acc); + return vehicleContainer; + } - var inTorque = tqNm.SI<NewtonMeter>(); - var outTortque = inTorque * gearRatios[gear]; + private IEngineInfo GetEngineInfo(Mock<IVehicleContainer> vehicleContainer, VectoRunData runData) + { + //EngineInfo + var engineInfo = new Mock<IEngineInfo>(); + vehicleContainer.Setup(c => c.EngineInfo).Returns(engineInfo.Object); + engineInfo.Setup(e => e.EngineIdleSpeed).Returns(runData.EngineData.IdleSpeed); + engineInfo.Setup(e => e.EngineRatedSpeed).Returns(runData.EngineData.FullLoadCurves.First().Value.RatedSpeed); - var response = new ResponseSuccess(this); - response.Engine.EngineSpeed = inAngularVelocity; - response.Engine.TorqueOutDemand = inTorque; + engineInfo.Setup(e => e.EngineSpeed).Returns(1400.RPMtoRad()); + engineInfo.Setup(e => e.EngineN95hSpeed).Returns + (runData.EngineData.FullLoadCurves.First().Value.N95hSpeed); + engineInfo.Setup(e => e.EngineN80hSpeed).Returns( + runData.EngineData.FullLoadCurves.First().Value.N80hSpeed); + engineInfo.Setup(e => e.EngineStationaryFullPower(It.IsAny<PerSecond>())).Returns((PerSecond n) => + runData.EngineData.FullLoadCurves[0].FullLoadStationaryPower(n)); + return engineInfo.Object; + } + private CycleData GetCycleData() + { + return new CycleData() { + LeftSample = new DrivingCycleData.DrivingCycleEntry() { + PTOActive = PTOActivity.Inactive, + VehicleTargetSpeed = 10.KMPHtoMeterPerSecond() + } + }; + } - var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, outTortque, outAngularVelocity, inTorque, inAngularVelocity, gbx.Gear, -double.MaxValue.SI<Second>(), response); + private Mock<IVehicleInfo> GetVehicleInfo(MeterPerSecond speed) + { + var vehicleInfo = new Mock<IVehicleInfo>(); + vehicleInfo.Setup(v => v.VehicleSpeed).Returns(speed); + vehicleInfo.Setup(v => v.AirDragResistance(It.IsAny<MeterPerSecond>(), It.IsAny<MeterPerSecond>())) + .Returns(0.SI<Newton>()); + vehicleInfo.Setup(v => v.RollingResistance(It.IsAny<Radian>())).Returns(0.SI<Newton>()); + vehicleInfo.Setup(v => v.SlopeResistance(It.IsAny<Radian>())).Returns(0.SI<Newton>()); + vehicleInfo.Setup(v => v.TotalMass).Returns(12000.SI<Kilogram>()); + return vehicleInfo; + } + private Mock<ITestPowertrain> GetMockTestPowertrain(VectoRunData runData, + out Mock<ISimpleVehicleContainer> simpleContainer) + { + var testPt = new Mock<ITestPowertrain>(); + simpleContainer = GetSimplePowertrain(runData, + out var testGearbox); - Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(newGear)); - Assert.That(shiftStrategy.NextGear.TorqueConverterLocked ?? true, Is.EqualTo(newTcLocked)); - var shiftExpected = gear != newGear; //Different Gear - shiftExpected = shiftRequired || gbx.Disengaged; //Gearbox was disengaged - Assert.AreEqual(shiftExpected, shiftRequired); - } -// -// -// -// - [TestCase(3, true, 2, true, 900, 600, 15, Description = "Downshift", TestName="Gearbox_DownShift_1")] - public void Gearbox_Downshift(int gear, bool tcLocked, int newGear, bool newTcLocked, double tqNm, double nRPM, double speedKmh) - { - var gearRatios = new[] { 3.4, 1.9, 1.42, 1.0, 0.7, 0.62 }; + testPt.Setup(t => t.Container).Returns(simpleContainer.Object); + testPt.Setup(t => t.Gearbox).Returns(testGearbox.Object); - var vehicleContainer = GetMockVehicleContainer( - speedKmh, - DrivingBehavior.Accelerating, - gearRatios, - out var inputData, out var runData, out var gearboxData, out var simplePt); + //Vehicle + var vehicle = new Mock<ITestPowertrainVehicle>(); + vehicle.Setup(v => v.Initialize( + It.IsAny<MeterPerSecond>(), + It.IsAny<Radian>())).Returns(new ResponseSuccess(this)); + testPt.Setup(t => t.Vehicle).Returns(vehicle.Object); - vehicleContainer.Setup(v => v.DriverInfo.DrivingAction).Returns(DrivingAction.Accelerate); - var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); - var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); + return testPt; + } - var gbxResponse = gbx.Initialize(0.SI<NewtonMeter>(), angularVelocity); + private Mock<IVehicleDeclarationInputData> GetMockInputData(double[]? gearRatios) + { + var input = new Mock<IVehicleDeclarationInputData>(); + var components = new Mock<IVehicleComponentsDeclaration>(); + input.Setup(i => i.Components).Returns(components.Object); + var gbx = new Mock<IGearboxDeclarationInputData>(); + var tc = new Mock<ITorqueConverterDeclarationInputData>(); - Assert.AreEqual((uint)gear, gbx.Gear.Gear); - Assert.That(gbx.Gear.TorqueConverterLocked, Is.EqualTo(tcLocked)); + components.Setup(c => c.GearboxInputData).Returns(gbx.Object); + components.Setup(c => c.TorqueConverterInputData).Returns(tc.Object); + gearRatios = gearRatios ?? new double[] { }; + var header = "Input Speed [rpm],Input Torque [Nm],Torque Loss [Nm]"; + var efficiency = 0.98; + var data = new List<string>(); + foreach (var speed in new[] { 0, 10000 }) { + foreach (var tq in new[] { 1e5, -1e5, 0 }) { + data.Add(FormattableString.Invariant($"{speed:f2}, {tq:f2}, {(1 - efficiency) * Math.Abs(tq)}")); + } + } - var absTime = 0.SI<Second>(); - var dt = 2.SI<Second>(); + var lossmap = InputDataHelper.InputDataAsTableData(header, data.ToArray()); + //lossmap.Columns + var gears = gearRatios.Select((x, idx) => { + var gear = new Mock<ITransmissionInputData>(); + gear.Setup(g => g.Ratio).Returns(x); + gear.Setup(g => g.Gear).Returns(idx + 1); + //gear.Setup(g => g.Efficiency).Returns(0.98); + gear.Setup(g => g.LossMap).Returns(lossmap); + gear.Setup(g => g.MaxInputSpeed).Returns(2000.RPMtoRad()); + return gear.Object; + }).ToList(); + gbx.Setup(g => g.Type).Returns(GearboxType.ATSerial); + gbx.Setup(g => g.Gears).Returns(gears); - gbx.CurrentState = new ATGearboxState() - { - Disengaged = gbx.Disengaged, - Gear = gbx.Gear, - }; + var tcData = InputDataHelper.InputDataAsTableData(TcHeader, TcData); + tc.Setup(t => t.TCData).Returns(tcData); + return input; + } + private static VectoRunData GetDummyVectoRunData(IVehicleDeclarationInputData inputData) + { + var nrOfGears = inputData.Components.GearboxInputData.Gears.Count; + var fldData = InputDataHelper.InputDataAsTableData(EngineFldHeader, EngineFldData); + var fld = FullLoadCurveReader.Create(fldData); - var inAngularVelocity = nRPM.RPMtoRad(); - var outAngularVelocity = inAngularVelocity / gearRatios[gear]; + // create gearbox data + var tcDataAdapter = new TorqueConverterDataAdapter(); - var inTorque = tqNm.SI<NewtonMeter>(); - var outTortque = inTorque * gearRatios[gear]; + // fuel data + var fuelData = new CombustionEngineFuelData() { + ConsumptionMap = FuelConsumptionMapReader.Create( + InputDataHelper.InputDataAsTableData( + "engine speed [rpm] ,torque [Nm] ,fuel consumption [g/h] ,whr power electrical [W]", + "500,-131,0,0", + "500,95.6,1814.959,0", + "500,573.6,9771.095,0", + "2453,-209.12,0,0", + "2453,764.8,39097.94,0" + )), + FuelData = DeclarationData.FuelData.Lookup(FuelType.DieselCI), + }; - var response = new ResponseSuccess(this); - response.Engine.EngineSpeed = inAngularVelocity; - response.Engine.TorqueOutDemand = inTorque; + var runData = new VectoRunData() { + VehicleData = new VehicleData() { + DynamicTyreRadius = 0.465.SI<Meter>(), + GrossVehicleMass = 12_000.SI<Kilogram>(), + CurbMass = 10_000.SI<Kilogram>(), + }, + EngineData = new CombustionEngineData() { + Inertia = 0.SI<KilogramSquareMeter>(), + FullLoadCurves = new Dictionary<uint, EngineFullLoadCurve>(), + IdleSpeed = 600.RPMtoRad(), + RatedSpeedDeclared = 2000.RPMtoRad(), + Fuels = new List<CombustionEngineFuelData>() { + fuelData, + } + }, + Cycle = new DrivingCycleData() { + CycleType = CycleType.DistanceBased + } + }; + for (uint i = 0; i <= nrOfGears; i++) { + runData.EngineData.FullLoadCurves[i] = fld; + } + var gbxDataAdapter = new GearboxDataAdapter(tcDataAdapter); + var gbxTypes = new[] { + GearboxType.ATSerial, GearboxType.ATPowerSplit + }; - var mockPort = new Mock<ITnOutPort>(); - - simplePt.Setup(s => s.GearboxOutPort).Returns(mockPort.Object); - mockPort.Setup(p => p.Request( - It.IsAny<Second>(), - It.IsAny<Second>(), - It.IsAny<NewtonMeter>(), - It.IsAny<PerSecond>(), - true - )).Returns((Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, bool dryRun) => { - var response = new ResponseDryRun(this); - response.Engine.PowerRequest = outTorque * outAngularVelocity; - return response; - }); + var gearboxData = gbxDataAdapter.CreateGearboxData(inputData, runData, + new ATShiftStrategyOptimizedPolygonCalculator(), new GearboxType[] { + GearboxType.ATSerial, + GearboxType.ATPowerSplit + }); + var gearShiftParams = + gbxDataAdapter.CreateGearshiftData(1.0, runData.EngineData.IdleSpeed, GearboxType.ATSerial, nrOfGears); + runData.GearboxData = gearboxData; + runData.GearshiftParameters = gearShiftParams; + return runData; + } + private Mock<ISimpleVehicleContainer> GetSimplePowertrain(VectoRunData runData, + out Mock<ITestPowertrainTransmission> testGearbox) + { + var simplePt = new Mock<ISimpleVehicleContainer>(); - var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, outTortque, outAngularVelocity, inTorque, inAngularVelocity, gbx.Gear, -double.MaxValue.SI<Second>(), response); + testGearbox = GetMockTestGearbox(runData.GearboxData.Gears); - Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(newGear)); - Assert.That(shiftStrategy.NextGear.TorqueConverterLocked ?? true, Is.EqualTo(newTcLocked)); + simplePt.Setup(s => s.GearboxInfo).Returns(testGearbox.Object); + simplePt.Setup(s => s.GearboxOutPort).Returns(testGearbox.Object); - var shiftExpected = gear != newGear; //Different Gear - shiftExpected = shiftRequired || gbx.Disengaged; //Gearbox was disengaged - Assert.AreEqual(shiftExpected, shiftRequired); - } -// -// [TestCase(3, true, 2, true, 200, 700, 15, Description = "Downshift_3", TestName = "Gearbox_DownShift_3")] -// public void Gearbox_Downshift_2(int gear, bool tcLocked, int newGear, bool newTcLocked, double tqNm, double nRPM, -// double speedKmh) -// { -// var gearRatios = new[] { 3.4, 1.9, 1.42, 1.0, 0.7, 0.62 }; -// -// var vehicleContainer = GetMockVehicleContainer( -// speedKmh, -// DrivingBehavior.Accelerating, -// gearRatios, -// out var inputData, out var runData, out var gearboxData, out _); -// -// vehicleContainer.Setup(v => v.DriverInfo.DrivingAction).Returns(DrivingAction.Accelerate); -// -// // Condition from ATShiftStrategy -// //if (DataBus.VehicleInfo.VehicleSpeed < DataBus.DrivingCycleInfo.CycleData.LeftSample.VehicleTargetSpeed - 10.KMPHtoMeterPerSecond() && -// // DataBus.DriverInfo.DriverAcceleration < 0.SI<MeterPerSquareSecond>()) -// vehicleContainer.Setup(v => v.DrivingCycleInfo.CycleData).Returns(new CycleData() { -// LeftSample = new DrivingCycleData.DrivingCycleEntry() { -// VehicleTargetSpeed = 30.KMPHtoMeterPerSecond() -// } -// }); -// -// vehicleContainer.Setup(v => v.DriverInfo.DriverAcceleration).Returns(-0.1.SI<MeterPerSquareSecond>()); -// -// -// runData.EngineData.Inertia = 1.SI<KilogramSquareMeter>(); -// var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx, out var gbxNextComponent); -// -// -// var dryRunResponse = new ResponseDryRun(this); -// dryRunResponse.Engine.EngineSpeed = -// vehicleContainer.Object.EngineInfo.EngineN95hSpeed - 1.SI<PerSecond>(); -// dryRunResponse.DeltaFullLoad = 40_000.SI<Watt>(); -// -// -// gbxNextComponent.Setup(c => c.Request( -// It.IsAny<Second>(), -// It.IsAny<Second>(), -// It.IsAny<NewtonMeter>(), -// It.IsAny<PerSecond>(), true)).Returns( -// dryRunResponse); -// -// var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); -// -// var response = gbx.Initialize(0.SI<NewtonMeter>(), angularVelocity); -// -// Assert.AreEqual((uint)gear, gbx.Gear.Gear); -// Assert.That(gbx.Gear.TorqueConverterLocked, Is.EqualTo(tcLocked)); -// -// -// var absTime = 0.SI<Second>(); -// var dt = 2.SI<Second>(); -// -// gbx.CurrentState = new ATGearbox.ATGearboxState() -// { -// Disengaged = gbx.Disengaged, -// Gear = gbx.Gear, -// }; -// -// -// var inAngularVelocity = nRPM.RPMtoRad(); -// var outAngularVelocity = inAngularVelocity / gearRatios[gear]; -// -// var inTorque = tqNm.SI<NewtonMeter>(); -// var outTortque = inTorque * gearRatios[gear]; -// -// var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, outTortque, outAngularVelocity, inTorque, inAngularVelocity, gbx.Gear, -double.MaxValue.SI<Second>(), new ResponseSuccess(this)); -// -// -// Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(newGear)); -// Assert.That(shiftStrategy.NextGear.TorqueConverterLocked ?? true, Is.EqualTo(newTcLocked)); -// -// var shiftExpected = gear != newGear; //Different Gear -// shiftExpected = shiftRequired || gbx.Disengaged; //Gearbox was disengaged -// -// Assert.AreEqual(shiftExpected, shiftRequired); -// } -// - [TestCase(3, true, 2, true, 1700, 700, 15, Description = "Downshift", TestName = "Gearbox_Early_DownShift_1")] - public void Gearbox_Early_Downshift(int gear, bool tcLocked, int newGear, bool newTcLocked, double tqNm, double nRPM, double speedKmh) - { - var gearRatios = new[] { 3.4, 1.9, 1.42, 1.0, 0.7, 0.62 }; - var vehicleContainer = GetMockVehicleContainer( - speedKmh, - DrivingBehavior.Accelerating, - gearRatios, - out var inputData, out var runData, out var gearboxData, out var simplePt); - vehicleContainer.Setup(v => v.DriverInfo.DrivingAction).Returns(DrivingAction.Accelerate); + //VehiclePort + return simplePt; + } - var shiftStrategy = GetShiftStrategyAndGearbox(vehicleContainer, out var gbx); - var angularVelocity = GetAngularVelocityBySpeed(speedKmh, runData); + private Mock<ITestPowertrainTransmission> GetMockTestGearbox(Dictionary<uint, GearData> ratios) + { + Mock<IAPTGearbox> amtGearbox = new Mock<IAPTGearbox>(); + amtGearbox.Name = "APT_TestGearbox"; + TestContext.WriteLine(amtGearbox.Name); + Mock<ITestPowertrainTransmission> gbx = amtGearbox.As<ITestPowertrainTransmission>(); - var gbxResponse = gbx.Initialize(0.SI<NewtonMeter>(), angularVelocity); - Assert.AreEqual((uint)gear, gbx.Gear.Gear); - Assert.That(gbx.Gear.TorqueConverterLocked, Is.EqualTo(tcLocked)); + gbx.Setup(g => g.LastUpshift).Returns(-double.MaxValue.SI<Second>()); + gbx.Setup(g => g.LastDownshift).Returns(-double.MaxValue.SI<Second>()); - var absTime = 0.SI<Second>(); - var dt = 2.SI<Second>(); + GearshiftPosition gear = null; + gbx.SetupGet(g => g.Gear).Returns(() => { return gear; }); + gbx.SetupSet(g => g.SetGear = It.IsAny<GearshiftPosition>()) + .Callback<GearshiftPosition>(p => { gear = p; }); - gbx.CurrentState = new ATGearboxState() - { - Disengaged = gbx.Disengaged, - Gear = gbx.Gear, - }; + GearshiftPosition nextGear = null; + gbx.SetupGet(g => g.NextGear).Returns(() => nextGear); + gbx.SetupSet(g => g.SetNextGear = It.IsAny<GearshiftPosition>()) + .Callback<GearshiftPosition>(p => nextGear = p); - var inAngularVelocity = nRPM.RPMtoRad(); - var outAngularVelocity = inAngularVelocity / gearRatios[gear]; + gbx.Setup(p => p.Initialize(It.IsAny<NewtonMeter>(), + It.IsAny<PerSecond>())).Returns((NewtonMeter tq, PerSecond rpm) => { + return new ResponseSuccess(this) { + Engine = { + EngineSpeed = rpm, + PowerRequest = tq * rpm, + }, + }; + }); + gbx.Setup(p => p.Request( + It.IsAny<Second>(), + It.IsAny<Second>(), + It.IsAny<NewtonMeter>(), + It.IsAny<PerSecond>(), + true)).Returns(( + Second absTime, + Second dt, + NewtonMeter t, + PerSecond n, + bool dryRun) => { - var inTorque = tqNm.SI<NewtonMeter>(); - var outTortque = inTorque * gearRatios[gear]; + var gear = gbx.Object.Gear.Gear; + var ratio = (gbx.Object.Gear.TorqueConverterLocked ?? false) + ? ratios[gear].Ratio + : ratios[gear].TorqueConverterRatio; - var response = new ResponseSuccess(this); - response.Engine.EngineSpeed = inAngularVelocity; - response.Engine.TorqueOutDemand = inTorque; + + + // var ratio = + // gbx.Object.Gear == null ? 1.0 : ratios[gbx.Object.Gear.Gear].Ratio; + return dryRun + ? new ResponseDryRun(this) { + Engine = { + PowerRequest = n * t, EngineSpeed = n * ratio, + DynamicFullLoadPower = (t / ratio + 2300.SI<NewtonMeter>()) * n * ratio, + TotalTorqueDemand = t, + TorqueOutDemand = t, + }, + Clutch = { PowerRequest = n * t }, + DeltaFullLoad = n * t / 2 * (-1) + } + : new ResponseSuccess(this) { + Engine = { + PowerRequest = n * t, + EngineSpeed = n * ratio + }, + Clutch = { PowerRequest = n * t } + }; + }); + return gbx; + } - var mockPort = new Mock<ITnOutPort>(); + private static PerSecond GetAngularVelocityBySpeed(double speedKmh, VectoRunData runData) + { + // r_dyn = 0.465m, i_axle = 6.2 + var angularVelocity = + speedKmh.KMPHtoMeterPerSecond() + / runData.VehicleData.DynamicTyreRadius * 6.2; + return angularVelocity; + } - simplePt.Setup(s => s.GearboxOutPort).Returns(mockPort.Object); - mockPort.Setup(p => p.Request( - It.IsAny<Second>(), - It.IsAny<Second>(), - It.IsAny<NewtonMeter>(), - It.IsAny<PerSecond>(), - true - )).Returns((Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, bool dryRun) => { - var response = new ResponseDryRun(this); - response.Engine.PowerRequest = outTorque * outAngularVelocity; - return response; - }); - var shiftRequired = shiftStrategy.ShiftRequired(absTime, dt, outTortque, outAngularVelocity, inTorque, inAngularVelocity, gbx.Gear, -double.MaxValue.SI<Second>(), response); + public const string TcHeader = "Speed Ratio, Torque Ratio,MP1000"; - Assert.That(shiftStrategy.NextGear.Gear, Is.EqualTo(newGear)); - Assert.That(shiftStrategy.NextGear.TorqueConverterLocked ?? true, Is.EqualTo(newTcLocked)); + public static readonly string[] TcData = new[] { + "0.0,1.80,377.80", + "0.1,1.71,365.21", + "0.2,1.61,352.62", + "0.3,1.52,340.02", + "0.4,1.42,327.43", + "0.5,1.33,314.84", + "0.6,1.23,302.24", + "0.7,1.14,264.46", + "0.8,1.04,226.68", + "0.9,1.02,188.90", + "1.0,1.0,0.00", + "1.100,0.999,-40.34", + "1.222,0.998,-80.34", + "1.375,0.997,-136.11", + "1.571,0.996,-216.52", + "1.833,0.995,-335.19", + "2.200,0.994,-528.77", + "2.750,0.993,-883.40", + "4.400,0.992,-2462.17", + "11.000,0.991,-16540.98", + }; - var shiftExpected = gear != newGear; //Different Gear - shiftExpected = shiftRequired || gbx.Disengaged; //Gearbox was disengaged + public const string EngineFldHeader = "engine speed [1/min],full load torque [Nm],motoring torque [Nm],PT1 [s]"; - Assert.AreEqual(shiftExpected, shiftRequired); - } - + public static readonly string[] EngineFldData = new[] { + "560,1180,-149,0.6", + "600,1282,-148,0.6", + "799.9999999,1791,-149,0.6", + "1000,2300,-160,0.6", + "1200,2300,-179,0.6", + "1400,2300,-203,0.6", + "1599.999999,2079,-235,0.49", + "1800,1857,-264,0.25", + "2000.000001,1352,-301,0.25", + "2100,1100,-320,0.25", + }; private ATShiftStrategyOptimized GetShiftStrategyAndGearbox(Mock<IVehicleContainer> vehicleContainer, - out APTGearbox gbx) + out Mock<IAPTGearbox> gbx) { return GetShiftStrategyAndGearbox(vehicleContainer, out gbx, out _); } private ATShiftStrategyOptimized GetShiftStrategyAndGearbox(Mock<IVehicleContainer> vehicleContainer, - out APTGearbox gbx, + out Mock<IAPTGearbox> gbx, out Mock<ITnOutPort> gbxNextComponent) { var shiftStrategy = new ATShiftStrategyOptimized(vehicleContainer.Object); - var gbxMock = new Mock<APTGearbox>(vehicleContainer.Object, shiftStrategy) { - CallBase = true - }; - - gbx = gbxMock.Object; - shiftStrategy.Gearbox = gbx; - - var mockPort = new Mock<ITnOutPort>(); - NewtonMeter tqRequest = null; - PerSecond rpmRequest = null; - - mockPort.Setup(p => p.Initialize(It.IsAny<NewtonMeter>(), - It.IsAny<PerSecond>())).Returns((NewtonMeter tq, PerSecond rpm) => { - tqRequest = tq; - rpmRequest = rpm; - return new ResponseSuccess(this) { - Engine = { - EngineSpeed = rpm, - PowerRequest = tq * rpm, - }, - }; - }); - - mockPort.Setup(p => p.Request(It.IsAny<Second>(), It.IsAny<Second>(), It.IsAny<NewtonMeter>(), - It.IsAny<PerSecond>(), true)).Returns(new ResponseDryRun(this)); + gbx = GetGearbox(vehicleContainer.Object.RunData); - var idleController = new Mock<IIdleController>(); + gbxNextComponent = null; - gbx.IdleController = idleController.Object; - gbx.Connect(mockPort.Object); - gbxNextComponent = mockPort; + shiftStrategy.Gearbox = gbx.Object; return shiftStrategy; + + // var gbxMock = new Mock<APTGearbox>(vehicleContainer.Object, shiftStrategy) { + // CallBase = true + // }; + // + // gbx = gbxMock.Object; + // shiftStrategy.Gearbox = gbx; + // + // var mockPort = new Mock<ITnOutPort>(); + // NewtonMeter tqRequest = null; + // PerSecond rpmRequest = null; + // + // mockPort.Setup(p => p.Initialize(It.IsAny<NewtonMeter>(), + // It.IsAny<PerSecond>())).Returns((NewtonMeter tq, PerSecond rpm) => { + // tqRequest = tq; + // rpmRequest = rpm; + // return new ResponseSuccess(this) { + // Engine = { + // EngineSpeed = rpm, + // PowerRequest = tq * rpm, + // }, + // }; + // }); + // + // mockPort.Setup(p => p.Request(It.IsAny<Second>(), It.IsAny<Second>(), It.IsAny<NewtonMeter>(), + // It.IsAny<PerSecond>(), true)).Returns(new ResponseDryRun(this)); + // + // var idleController = new Mock<IIdleController>(); + // + // + // gbx.IdleController = idleController.Object; + // gbx.Connect(mockPort.Object); + // + // gbxNextComponent = mockPort; + // return shiftStrategy; } -} - -// private Mock<IVehicleContainer> GetMockVehicleContainer(double speedKmh, DrivingBehavior driverBehavior, -// double[] gearRatios, -// out IVehicleDeclarationInputData inputData, out VectoRunData runData, out GearboxData gearboxData, -// out Mock<ISimpleVehicleContainer> simplePt) -// { -// inputData = GetMockInputData(gearRatios); -// var gbxTypes = new[] { -// GearboxType.ATSerial -// }; -// var runDataLocal = GetDummyVectoRunData(inputData); -// var shiftPolygonCalc = GetShiftPolygonCalculator(true); -// -// -// //Setup VehicleContainer -// var vehicleContainer = new Mock<IVehicleContainer>(); -// var vehicleInfo = new Mock<IVehicleInfo>(); -// -// vehicleContainer.Setup(c => c.RunData).Returns(runDataLocal); -// vehicleContainer.Setup(c => c.VehicleInfo).Returns(vehicleInfo.Object); -// -// -// //EngineInfo -// var engineInfo = new Mock<IEngineInfo>(); -// vehicleContainer.Setup(c => c.EngineInfo).Returns(engineInfo.Object); -// engineInfo.Setup(e => e.EngineIdleSpeed).Returns(runDataLocal.EngineData.IdleSpeed); -// engineInfo.Setup(e => e.EngineRatedSpeed).Returns(runDataLocal.EngineData.FullLoadCurves.First().Value.RatedSpeed); -// -// engineInfo.Setup(e => e.EngineSpeed).Returns(1400.RPMtoRad()); -// engineInfo.Setup(e => e.EngineN95hSpeed).Returns -// (runDataLocal.EngineData.FullLoadCurves.First().Value.N95hSpeed); -// engineInfo.Setup(e => e.EngineN80hSpeed).Returns( -// runDataLocal.EngineData.FullLoadCurves.First().Value.N80hSpeed); -// engineInfo.Setup(e => e.EngineStationaryFullPower(It.IsAny<PerSecond>())).Returns((PerSecond n) => -// runDataLocal.EngineData.FullLoadCurves[0].FullLoadStationaryPower(n)); -// -// //VehicleInfo -// vehicleInfo.Setup(v => v.VehicleSpeed).Returns(speedKmh.KMPHtoMeterPerSecond()); -// vehicleInfo.Setup(v => v.AirDragResistance(It.IsAny<MeterPerSecond>(), It.IsAny<MeterPerSecond>())) -// .Returns(0.SI<Newton>()); -// vehicleInfo.Setup(v => v.RollingResistance(It.IsAny<Radian>())).Returns(0.SI<Newton>()); -// vehicleInfo.Setup(v => v.SlopeResistance(It.IsAny<Radian>())).Returns(0.SI<Newton>()); -// vehicleInfo.Setup(v => v.TotalMass).Returns(12000.SI<Kilogram>()); -// -// //AxleGearInfo -// var axleGearInfo = new Mock<IAxlegearInfo>(); -// vehicleContainer.Setup(c => c.AxlegearInfo).Returns(axleGearInfo.Object); -// axleGearInfo.Setup(a => a.AxlegearLoss()).Returns(0.SI<Watt>()); -// -// //WheelsInfo -// var wi = new Mock<IWheelsInfo>(); -// vehicleContainer.Setup(c => c.WheelsInfo).Returns(wi.Object); -// wi.Setup(w => w.ReducedMassWheels).Returns(0.SI<Kilogram>()); -// -// //Cycle Info -// var cycleInfo = new Mock<IDrivingCycleInfo>(); -// vehicleContainer.Setup(c => c.DrivingCycleInfo).Returns(cycleInfo.Object); -// cycleInfo.Setup(c => c.CycleData).Returns( -// GetCycleData()); -// cycleInfo.Setup(c => c.RoadGradient).Returns(0.SI<Radian>()); -// -// -// cycleInfo.Setup(c => c.CycleLookAhead(It.IsAny<Meter>())).Returns(new DrivingCycleData.DrivingCycleEntry() -// { -// Altitude = 0.SI<Meter>() -// }); -// cycleInfo.Setup(c => c.Altitude).Returns(0.SI<Meter>()); -// -// //DriverINfo -// vehicleContainer.Setup(v => v.DriverInfo.DriverBehavior).Returns(driverBehavior); -// var acc = 0.SI<MeterPerSquareSecond>(); -// switch (driverBehavior) -// { -// case DrivingBehavior.Accelerating: -// acc = 1.SI<MeterPerSquareSecond>(); -// break; -// case DrivingBehavior.Braking: -// acc = -1.SI<MeterPerSquareSecond>(); -// break; -// case DrivingBehavior.Halted: -// acc = 0.SI<MeterPerSquareSecond>(); -// break; -// default: -// throw new ArgumentOutOfRangeException(); -// } -// -// -// -// -// vehicleContainer.Setup(v => v.DriverInfo.DriverAcceleration).Returns(acc); -// runData = runDataLocal; -// gearboxData = runData.GearboxData; -// -// -// //TestPowertrain -// //TestPowertrainBuilder -// var testPt = GetMockTestPowertrain(runData); -// -// var ptBuilder = new Mock<ISimplePowertrainBuilder>(); -// ptBuilder.Setup(p => p.CreateTestPowertrain<Gearbox>(It.IsAny<ISimpleVehicleContainer>(), It.IsAny<IDataBus>())) -// .Returns(testPt.Object); -// simplePt = GetSimplePowertrain(inputData); -// ptBuilder.Setup(ptBuilder => ptBuilder.BuildSimplePowertrain(It.IsAny<VectoRunData>())) -// .Returns(simplePt.Object); -// -// -// vehicleContainer.Setup(c => c.SimplePowertrainBuilder).Returns(ptBuilder.Object); -// -// return vehicleContainer; -// } -// -// private Mock<IPowertainInfo> GetPowertrainInfo() -// { -// var powerTrainInfo = new Mock<IPowertainInfo>(); -// powerTrainInfo.Setup(p => p.HasCombustionEngine).Returns(true); -// return powerTrainInfo; -// } -// -// private Mock<ITestPowertrain<Gearbox>> GetMockTestPowertrain(VectoRunData runData) -// { -// var testPt = new Mock<ITestPowertrain<Gearbox>>(); -// var tCnt = new Mock<ISimpleVehicleContainer>(); -// tCnt.Setup(c => c.RunData).Returns(runData); -// -// tCnt.Setup(c => c.PowertrainInfo).Returns(GetPowertrainInfo().Object); -// -// -// var tGbx = new Mock<Gearbox>(tCnt.Object, null); -// testPt.Setup(t => t.Gearbox).Returns(tGbx.Object); -// tGbx.Setup(g => g.Initialize(It.IsAny<NewtonMeter>(), It.IsAny<PerSecond>())) -// .Returns((NewtonMeter t, PerSecond n) => new ResponseSuccess(this) -// { -// Engine = { PowerRequest = n * t, EngineSpeed = n }, -// Clutch = { PowerRequest = n * t } -// }); -// tGbx.Setup(g => g.Request(It.IsAny<Second>(), It.IsAny<Second>(), It.IsAny<NewtonMeter>(), It.IsAny<PerSecond>(), -// It.IsAny<bool>())) -// .Returns((Second absTime, Second dt, NewtonMeter t, PerSecond n, bool dryRun) => new ResponseSuccess(this) -// { -// Engine = { PowerRequest = n * t, EngineSpeed = n }, -// Clutch = { PowerRequest = n * t } -// }); -// tGbx.Setup(g => g.Request(It.IsAny<Second>(), It.IsAny<Second>(), It.IsAny<NewtonMeter>(), It.IsAny<PerSecond>(), -// It.IsAny<bool>())) -// .Returns((Second absTime, Second dt, NewtonMeter t, PerSecond n, bool dryRun) => dryRun ? -// new ResponseDryRun(this) -// { -// Engine = { PowerRequest = n * t, EngineSpeed = n }, -// Clutch = { PowerRequest = n * t } -// } : new ResponseSuccess(this) -// { -// Engine = { PowerRequest = n * t, EngineSpeed = n }, -// Clutch = { PowerRequest = n * t } -// }); -// var tEng = new Mock<ICombustionEngine>(); -// testPt.Setup(t => t.CombustionEngine).Returns(tEng.Object); -// tEng.Setup(e => e.EngineStationaryFullPower(It.IsAny<PerSecond>())) -// .Returns((PerSecond n) => runData.EngineData.FullLoadCurves[0].FullLoadStationaryPower(n)); -// return testPt; -// } -// -// private CycleData GetCycleData() -// { -// return new CycleData() -// { -// LeftSample = new DrivingCycleData.DrivingCycleEntry() -// { -// PTOActive = PTOActivity.Inactive, -// VehicleTargetSpeed = 10.KMPHtoMeterPerSecond() -// } -// }; -// } -// -// -// -// private static VectoRunData GetDummyVectoRunData(IVehicleDeclarationInputData inputData) -// { -// var nrOfGears = inputData.Components.GearboxInputData.Gears.Count; -// var fldData = InputDataHelper.InputDataAsTableData(EngineFldHeader, EngineFldData); -// var fld = FullLoadCurveReader.Create(fldData); -// -// -// // create gearbox data -// var tcDataAdapter = new TorqueConverterDataAdapter(); -// -// -// -// // fuel data -// var fuelData = new CombustionEngineFuelData() { -// ConsumptionMap = FuelConsumptionMapReader.Create( -// InputDataHelper.InputDataAsTableData( -// "engine speed [rpm] ,torque [Nm] ,fuel consumption [g/h] ,whr power electrical [W]", -// "500,-131,0,0", -// "500,95.6,1814.959,0", -// "500,573.6,9771.095,0", -// "2453,-209.12,0,0", -// "2453,764.8,39097.94,0" -// )), -// FuelData = DeclarationData.FuelData.Lookup(FuelType.DieselCI), -// -// -// }; -// -// var runData = new VectoRunData() { -// VehicleData = new VehicleData() { -// DynamicTyreRadius = 0.465.SI<Meter>(), -// GrossVehicleMass = 12_000.SI<Kilogram>(), -// CurbMass = 10_000.SI<Kilogram>(), -// }, -// EngineData = new CombustionEngineData() { -// Inertia = 0.SI<KilogramSquareMeter>(), -// FullLoadCurves = new Dictionary<uint, EngineFullLoadCurve>(), -// IdleSpeed = 600.RPMtoRad(), -// RatedSpeedDeclared = 2000.RPMtoRad(), -// Fuels = new List<CombustionEngineFuelData>() { -// fuelData, -// } -// }, -// Cycle = new DrivingCycleData() { -// CycleType = CycleType.DistanceBased -// } -// }; -// for (uint i = 0; i <= nrOfGears; i++) { -// runData.EngineData.FullLoadCurves[i] = fld; -// } -// -// var gbxDataAdapter = new GearboxDataAdapter(tcDataAdapter); -// var gbxTypes = new[] { -// GearboxType.ATSerial, GearboxType.ATPowerSplit -// }; -// -// var gearboxData = gbxDataAdapter.CreateGearboxData(inputData, runData, new ATShiftStrategyOptimizedPolygonCalculator(), new GearboxType[] { -// GearboxType.ATSerial, -// GearboxType.ATPowerSplit -// }); -// -// var gearShiftParams = -// gbxDataAdapter.CreateGearshiftData(1.0, runData.EngineData.IdleSpeed, GearboxType.ATSerial, nrOfGears); -// -// runData.GearboxData = gearboxData; -// runData.GearshiftParameters = gearShiftParams; -// return runData; -// } -// -// private static IShiftPolygonCalculator GetShiftPolygonCalculator(bool optimized) -// { -// -// IShiftPolygonCalculator shiftPolygonCalc = optimized ? new ATShiftStrategyOptimizedPolygonCalculator() : new ATShiftStrategyPolygonCalculator(); -// -// return shiftPolygonCalc; -// } -// -// // private static IShiftPolygonCalculator GetMockShiftPolygonCalc() -// // { -// // var shiftPolygonCalc = new Mock<IShiftPolygonCalculator>(); -// // var downshift = new List<ShiftPolygon.ShiftPolygonEntry>() { }; -// // var upshift = new List<ShiftPolygon.ShiftPolygonEntry>() { }; -// // var shiftpolygon = new ShiftPolygon(downshift, upshift); -// // shiftPolygonCalc.Setup(s => s.ComputeDeclarationShiftPolygon(It.IsIn(GearboxType.ATSerial), It.IsAny<int>(), -// // It.IsAny<EngineFullLoadCurve>(), It.IsAny<IList<ITransmissionInputData>>(), -// // It.IsAny<CombustionEngineData>(), It.IsAny<double>(), It.IsAny<Meter>(), It.IsAny<ElectricMotorData>())) -// // .Returns(shiftpolygon); -// // return shiftPolygonCalc.Object; -// // } -// -// private Mock<ISimpleVehicleContainer> GetSimplePowertrain(IVehicleDeclarationInputData inputData) -// { -// var simplePt = new Mock<ISimpleVehicleContainer>(); -// simplePt.Setup(s => s.RunData).Returns(GetDummyVectoRunData(inputData)); -// simplePt.Setup(s => s.AddComponent(It.IsAny<VectoSimulationComponent>())); -// simplePt.Setup(s => s.PowertrainInfo).Returns(GetPowertrainInfo().Object); -// simplePt.Setup(s => s.GearboxCtl).Returns(GetMockGearbox(simplePt.Object).Object); -// -// //Vehicle Info -// var vehicleInfo = new Mock<IVehicleInfo>(); -// simplePt.Setup(c => c.VehicleInfo).Returns(vehicleInfo.Object); -// vehicleInfo.Setup(v => v.VehicleSpeed).Returns(1.KMPHtoMeterPerSecond()); -// -// -// //VehiclePort -// var vehiclePort = new Mock<IDriverDemandOutPort>(); -// vehiclePort.Setup(port => port.Initialize( -// It.IsAny<MeterPerSecond>(), It.IsAny<Radian>())).Returns(new ResponseSuccess(this)); -// -// simplePt.Setup(c => c.VehiclePort).Returns(vehiclePort.Object); -// -// var mockPort = new Mock<ITnOutPort>(); -// -// mockPort.Setup(p => p.Initialize(It.IsAny<NewtonMeter>(), -// It.IsAny<PerSecond>())).Returns((NewtonMeter tq, PerSecond rpm) => { -// return new ResponseSuccess(this) -// { -// Engine = { -// EngineSpeed = rpm, -// PowerRequest = tq * rpm, -// }, -// }; -// }); -// mockPort.Setup(p => p.Request( -// It.IsAny<Second>(), -// It.IsAny<Second>(), -// It.IsAny<NewtonMeter>(), -// It.IsAny<PerSecond>(), -// true)).Returns(( -// Second absTime, -// Second dt, -// NewtonMeter tq, -// PerSecond ang, -// bool dryRun) => { -// return new ResponseDryRun(this) { -// Engine = { -// EngineSpeed = ang, -// PowerRequest = tq * ang, -// TorqueOutDemand = tq -// }, -// DeltaFullLoad = 10_000.SI<Watt>(), -// }; -// }); -// -// simplePt.Setup(c => c.GearboxOutPort).Returns(mockPort.Object); -// return simplePt; -// } -// private Mock<ATGearbox> GetMockGearbox(IVehicleContainer container) -// { -// var gbx = new Mock<ATGearbox>(container, null); -// var ratios = container.RunData.GearboxData.Gears; -// -// -// gbx.Setup(g => g.LastUpshift).Returns(-double.MaxValue.SI<Second>()); -// gbx.Setup(g => g.LastDownshift).Returns(-double.MaxValue.SI<Second>()); -// gbx.SetupProperty(g => g.Gear); -// gbx.Setup(g => g.Request(It.IsAny<Second>(), It.IsAny<Second>(), It.IsAny<NewtonMeter>(), It.IsAny<PerSecond>(), -// It.IsAny<bool>())) -// .Returns((Second absTime, Second dt, NewtonMeter t, PerSecond n, bool dryRun) => { -// var ratio = gbx.Object.Gear == null ? 1.0 : ratios[gbx.Object.Gear.Gear].Ratio; -// return dryRun -// ? new ResponseDryRun(this) -// { -// Engine = { -// PowerRequest = n * t, EngineSpeed = n * ratio, -// DynamicFullLoadPower = (t / ratio + 2300.SI<NewtonMeter>()) * n * ratio, -// }, -// Clutch = { PowerRequest = n * t }, -// DeltaFullLoad = 10.SI<Watt>() -// } -// : new ResponseSuccess(this) -// { -// Engine = { PowerRequest = n * t, EngineSpeed = n * ratio }, -// Clutch = { PowerRequest = n * t } -// }; -// }); -// return gbx; -// } -// -// -// private IVehicleDeclarationInputData GetMockInputData(double[]? gearRatios) -// { -// var input = new Mock<IVehicleDeclarationInputData>(); -// var components = new Mock<IVehicleComponentsDeclaration>(); -// input.Setup(i => i.Components).Returns(components.Object); -// var gbx = new Mock<IGearboxDeclarationInputData>(); -// var tc = new Mock<ITorqueConverterDeclarationInputData>(); -// -// components.Setup(c => c.GearboxInputData).Returns(gbx.Object); -// components.Setup(c => c.TorqueConverterInputData).Returns(tc.Object); -// gearRatios = gearRatios ?? new double[] { -// -// }; -// var header = "Input Speed [rpm],Input Torque [Nm],Torque Loss [Nm]"; -// var efficiency = 0.98; -// var data = new List<string>(); -// -// foreach (var speed in new[] {0, 10000}) { -// foreach (var tq in new[] {1e5, -1e5, 0}) { -// data.Add(FormattableString.Invariant($"{speed:f2}, {tq:f2}, {(1 - efficiency) * Math.Abs(tq)}")); -// } -// } -// var lossmap = InputDataHelper.InputDataAsTableData(header, data.ToArray()); -// //lossmap.Columns -// var gears = gearRatios.Select((x, idx) => { -// var gear = new Mock<ITransmissionInputData>(); -// gear.Setup(g => g.Ratio).Returns(x); -// gear.Setup(g => g.Gear).Returns(idx + 1); -// //gear.Setup(g => g.Efficiency).Returns(0.98); -// gear.Setup(g => g.LossMap).Returns(lossmap); -// gear.Setup(g => g.MaxInputSpeed).Returns(2000.RPMtoRad()); -// return gear.Object; -// }).ToList(); -// gbx.Setup(g => g.Type).Returns(GearboxType.ATSerial); -// gbx.Setup(g => g.Gears).Returns(gears); -// -// var tcData = InputDataHelper.InputDataAsTableData(TcHeader, TcData); -// tc.Setup(t => t.TCData).Returns(tcData); -// return input.Object; -// } -// -// public const string TcHeader = "Speed Ratio, Torque Ratio,MP1000"; -// -// public static readonly string[] TcData = new[] { -// "0.0,1.80,377.80", -// "0.1,1.71,365.21", -// "0.2,1.61,352.62", -// "0.3,1.52,340.02", -// "0.4,1.42,327.43", -// "0.5,1.33,314.84", -// "0.6,1.23,302.24", -// "0.7,1.14,264.46", -// "0.8,1.04,226.68", -// "0.9,1.02,188.90", -// "1.0,1.0,0.00", -// "1.100,0.999,-40.34", -// "1.222,0.998,-80.34", -// "1.375,0.997,-136.11", -// "1.571,0.996,-216.52", -// "1.833,0.995,-335.19", -// "2.200,0.994,-528.77", -// "2.750,0.993,-883.40", -// "4.400,0.992,-2462.17", -// "11.000,0.991,-16540.98", -// }; -// -// public const string EngineFldHeader = "engine speed [1/min],full load torque [Nm],motoring torque [Nm],PT1 [s]"; -// -// public static readonly string[] EngineFldData = new[] { -// "560,1180,-149,0.6", -// "600,1282,-148,0.6", -// "799.9999999,1791,-149,0.6", -// "1000,2300,-160,0.6", -// "1200,2300,-179,0.6", -// "1400,2300,-203,0.6", -// "1599.999999,2079,-235,0.49", -// "1800,1857,-264,0.25", -// "2000.000001,1352,-301,0.25", -// "2100,1100,-320,0.25", -// }; -// -// -// } \ No newline at end of file + + private static Mock<IAPTGearbox> GetGearbox(VectoRunData objectRunData) + { + Mock<IAPTGearbox> gbx; + gbx = new Mock<IAPTGearbox>(MockBehavior.Strict); + gbx.Name = "MockGearbox"; + TestContext.WriteLine(gbx.Name); + bool disengaged = false; + gbx.SetupGet(g => g.Disengaged).Returns(() => disengaged); + gbx.SetupSet(g => g.Disengaged = It.IsAny<bool>()).Callback((bool value) => disengaged = value); + + gbx.Setup(g => g.ComputeShiftLosses( + It.IsAny<NewtonMeter>(), + It.IsAny<PerSecond>(), + It.IsAny<GearshiftPosition>())).Returns((NewtonMeter outT, PerSecond outN, GearshiftPosition gear) => + { + return 0.SI<WattSecond>(); + }); + gbx.Setup(g => g.EngineInertia).Returns(objectRunData.EngineData.Inertia); + + //TorqueConverter + var tq = new Mock<ITorqueConverter>(MockBehavior.Strict); + gbx.Setup(g => g.TorqueConverter).Returns(tq.Object); + tq.Setup(tq => tq.FindOperatingPoint( + It.IsAny<Second>(), + It.IsAny<Second>(), + It.IsAny<NewtonMeter>(), + It.IsAny<PerSecond>())).Returns((Second t, Second dt, NewtonMeter outTorque, PerSecond outSpeed) => { + var speedRatio = 1.0; + var torqueRatio = 1.0; + return new TorqueConverterOperatingPoint() { + Creeping = false, + InAngularVelocity = speedRatio * outSpeed, + OutAngularVelocity = outSpeed, + InTorque = torqueRatio * outTorque, + OutTorque = outTorque, + SpeedRatio = speedRatio, + TorqueRatio = torqueRatio + }; + }); + return gbx; + } +} \ No newline at end of file diff --git a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/MTShiftStrategyTests.cs b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/MTShiftStrategyTests.cs index 098055db3f..ea2e1b9504 100644 --- a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/MTShiftStrategyTests.cs +++ b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/MTShiftStrategyTests.cs @@ -335,37 +335,13 @@ public class MTShiftStrategyTests private Mock<IGearbox> GetMockGearbox() { - var mtGbx = new Mock<IMTGearbox>(); + var mtGbx = new Mock<IMTGearbox>(MockBehavior.Strict); var gbx = mtGbx.As<IGearbox>(); gbx.Setup(g => g.LastUpshift).Returns(-double.MaxValue.SI<Second>()); gbx.Setup(g => g.LastDownshift).Returns(-double.MaxValue.SI<Second>()); return gbx; - // var gbx = new Mock<DeclarationData.Gearbox>(container, null); - // var ratios = container.RunData.GearboxData.Gears; - - // - - // gbx.SetupProperty(g => g.Gear); - // gbx.Setup(g => g.Request(It.IsAny<Second>(), It.IsAny<Second>(), It.IsAny<NewtonMeter>(), It.IsAny<PerSecond>(), - // It.IsAny<bool>())) - // .Returns((Second absTime, Second dt, NewtonMeter t, PerSecond n, bool dryRun) => { - // var ratio = gbx.Object.Gear == null ? 1.0 : ratios[gbx.Object.Gear.Gear].Ratio; - // return dryRun - // ? new ResponseDryRun(this) { - // Engine = { - // PowerRequest = n * t, EngineSpeed = n * ratio, - // DynamicFullLoadPower = (t / ratio + 2300.SI<NewtonMeter>()) * n * ratio, - // }, - // Clutch = { PowerRequest = n * t } - // } - // : new ResponseSuccess(this) { - // Engine = { PowerRequest = n * t, EngineSpeed = n * ratio }, - // Clutch = { PowerRequest = n * t } - // }; - // }); - // return gbx; } diff --git a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/PEVAMTShiftStrategyTests.cs b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/PEVAMTShiftStrategyTests.cs index e140fa06e3..e6c7260548 100644 --- a/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/PEVAMTShiftStrategyTests.cs +++ b/Testing/UnitTests/Vecto UnitTests/TestCases/Components/GearShiftStrategy/PEVAMTShiftStrategyTests.cs @@ -141,8 +141,8 @@ namespace TUGraz.Vecto.UnitTests.TestCases.Components.GearShiftStrategy var shiftRequired = currentGear != expectedGear; var shiftStrategy = GetShiftStrategyAndGearbox(container, out var gearbox); - var gear = new GearshiftPosition((uint)currentGear); - gearbox.Gear = gear; + // var gear = new GearshiftPosition((uint)currentGear); + // gearbox.Gear = gear; var absTime = 0.SI<Second>(); var dt = 0.5.SI<Second>(); @@ -209,8 +209,8 @@ namespace TUGraz.Vecto.UnitTests.TestCases.Components.GearShiftStrategy var shiftRequired = currentGear != expectedGear; var shiftStrategy = GetShiftStrategyAndGearbox(container, out var gearbox); - var gear = new GearshiftPosition((uint)currentGear); - gearbox.Gear = gear; + // var gear = new GearshiftPosition((uint)currentGear); + // gearbox.Gear = gear; var absTime = 0.SI<Second>(); var dt = 0.5.SI<Second>(); @@ -344,8 +344,8 @@ namespace TUGraz.Vecto.UnitTests.TestCases.Components.GearShiftStrategy var shiftRequired = currentGear != expectedGear; var shiftStrategy = GetShiftStrategyAndGearbox(container, out var gearbox); - var gear = new GearshiftPosition((uint)currentGear); - gearbox.Gear = gear; + // var gear = new GearshiftPosition((uint)currentGear); + // gearbox.Gear = gear; var absTime = 0.SI<Second>(); var dt = 0.5.SI<Second>(); @@ -423,8 +423,8 @@ namespace TUGraz.Vecto.UnitTests.TestCases.Components.GearShiftStrategy var shiftRequired = currentGear != expectedGear; var shiftStrategy = GetShiftStrategyAndGearbox(container, out var gearbox); - var gear = new GearshiftPosition((uint)currentGear); - gearbox.Gear = gear; + // var gear = new GearshiftPosition((uint)currentGear); + // gearbox.Gear = gear; var absTime = 0.SI<Second>(); var dt = 0.5.SI<Second>(); @@ -480,20 +480,36 @@ namespace TUGraz.Vecto.UnitTests.TestCases.Components.GearShiftStrategy - private PEVAMTShiftStrategy GetShiftStrategyAndGearbox(Mock<IVehicleContainer> container, out PEVGearbox gearbox) + private PEVAMTShiftStrategy GetShiftStrategyAndGearbox(Mock<IVehicleContainer> container, + out Mock<IPEVGearbox> gearbox) { var shiftStrategy = new PEVAMTShiftStrategy(container.Object); - gearbox = new PEVGearbox(container.Object, shiftStrategy); + + // gearbox = new PEVGearbox(container.Object, shiftStrategy); SetVelocityDropLookupData(shiftStrategy); - - gearbox.Gear = new GearshiftPosition(0); - container.Setup(c => c.GearboxInfo).Returns(gearbox); - - + + var gbx = GetGearbox(); + // gearbox.Gear = new GearshiftPosition(0); + // container.Setup(c => c.GearboxInfo).Returns(gearbox); + + gearbox = gbx; + + shiftStrategy.Gearbox = gbx.Object; return shiftStrategy; } + private Mock<IPEVGearbox> GetGearbox() + { + var gbx = new Mock<IPEVGearbox>(MockBehavior.Strict); + gbx.Setup(g => g.LastUpshift).Returns(-double.MaxValue.SI<Second>()); + gbx.Setup(g => g.LastDownshift).Returns(-double.MaxValue.SI<Second>()); + + + + return gbx; + } + private Mock<IVehicleContainer> GetMocks(double[] ratios) { var container = new Mock<IVehicleContainer>(); diff --git a/VectoCore/VectoCore/Models/SimulationComponent/IGearbox.cs b/VectoCore/VectoCore/Models/SimulationComponent/IGearbox.cs index 81aa795e99..0514204f9c 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/IGearbox.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/IGearbox.cs @@ -66,7 +66,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent new bool Disengaged { get; set; } KilogramSquareMeter EngineInertia { get; } - TorqueConverter TorqueConverter { get; } + ITorqueConverter TorqueConverter { get; } WattSecond ComputeShiftLosses(NewtonMeter outTorque, PerSecond outAngularVelocity, GearshiftPosition nextGearPos); } @@ -77,5 +77,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent public interface IIEPCGearbox : ITypedGearbox { } - public interface ITorqueConverter : ITorqueConverterInfo, ITorqueConverterControl, IUpdateable { } + public interface ITorqueConverter : ITorqueConverterInfo, ITorqueConverterControl, IUpdateable + { + TorqueConverterOperatingPoint FindOperatingPoint(Second absTime, Second dt, NewtonMeter nextGearboxInTorque, PerSecond nextGearboxInSpeed); + } } \ No newline at end of file diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Gearbox/APTGearbox.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Gearbox/APTGearbox.cs index 47c608f540..034dcf053e 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Gearbox/APTGearbox.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Gearbox/APTGearbox.cs @@ -61,6 +61,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Gearbox //set { CurrentState.TorqueConverterLocked = value; } public override bool TCLocked => Gear.TorqueConverterLocked.Value; + ITorqueConverter IAPTGearbox.TorqueConverter + { + get => TorqueConverter; + } public TorqueConverter TorqueConverter { get; diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Shiftstrategies/AMTShiftStrategy.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Shiftstrategies/AMTShiftStrategy.cs index e87e0803c3..29cd502e7e 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Shiftstrategies/AMTShiftStrategy.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Shiftstrategies/AMTShiftStrategy.cs @@ -56,7 +56,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies protected ITestPowertrain TestPowertrain; - protected AMTGearbox _gearbox; + protected IAMTGearbox _gearbox; public AMTShiftStrategy(IVehicleContainer container) : base(container) { @@ -90,7 +90,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies public override IGearbox Gearbox { get => _gearbox; set { - if (value is AMTGearbox gbx) { + if (value is IAMTGearbox gbx) { _gearbox = gbx; return; } @@ -376,10 +376,22 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies protected virtual ResponseDryRun RequestDryRunWithGear( Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, GearshiftPosition tryNextGear) { - var tmpGear = Gearbox.Gear; - _gearbox.Gear = tryNextGear; - var response = (ResponseDryRun)_gearbox.Request(absTime, dt, outTorque, outAngularVelocity, true); - _gearbox.Gear = tmpGear; + // var tmpGear = Gearbox.Gear; + // _gearbox.Gear = tryNextGear; + // var response = (ResponseDryRun)_gearbox.Request(absTime, dt, outTorque, outAngularVelocity, true); + // _gearbox.Gear = tmpGear; + + + + LogEnabled = false; + TestPowertrain.UpdateComponents(); + TestPowertrain.Gearbox.SetDisengaged = false; + TestPowertrain.Gearbox.SetGear = tryNextGear; + + TestPowertrain.Container.GearboxOutPort.Initialize(outTorque, outAngularVelocity); + var response = (ResponseDryRun)TestPowertrain.Container.GearboxOutPort.Request( + 0.SI<Second>(), dt, outTorque, outAngularVelocity, true); + LogEnabled = true; return response; } } diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Shiftstrategies/ATShiftStrategyOptimized.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Shiftstrategies/ATShiftStrategyOptimized.cs index 59737053e1..d46b0c35ee 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Shiftstrategies/ATShiftStrategyOptimized.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Shiftstrategies/ATShiftStrategyOptimized.cs @@ -38,7 +38,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies protected List<SchmittTrigger> LoadStageSteps = new List<SchmittTrigger>(); protected ShiftLineSet UpshiftLineTCLocked = new ShiftLineSet(); - protected APTGearbox _gearbox; + protected IAPTGearbox _gearbox; public ATShiftStrategyOptimized(IVehicleContainer container) : base(container) { @@ -68,7 +68,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies public override IGearbox Gearbox { get => _gearbox; set { - if (value is APTGearbox gbx) { + if (value is IAPTGearbox gbx) { _gearbox = gbx; return; } @@ -151,7 +151,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl.Shiftstrategies } foreach (var gear in Gears.Reverse()) { - var response = _gearbox.Initialize(gear, torque, outAngularVelocity); + var response = RequestDryRunWithGear(absTime, dt, torque, outAngularVelocity, gear); + //var response = _gearbox.Initialize(gear, torque, outAngularVelocity); if (response.Engine.EngineSpeed > Container.EngineInfo.EngineRatedSpeed || response.Engine.EngineSpeed < Container.EngineInfo.EngineIdleSpeed) { continue; diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/TorqueConverter.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/TorqueConverter.cs index c085ed588e..49834ecee4 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/TorqueConverter.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/TorqueConverter.cs @@ -426,7 +426,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return retVal; } - protected internal TorqueConverterOperatingPoint FindOperatingPoint(Second absTime, Second dt, + public TorqueConverterOperatingPoint FindOperatingPoint(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity) { -- GitLab