diff --git a/VectoCore/VectoCore/Models/Connector/Ports/Impl/Response.cs b/VectoCore/VectoCore/Models/Connector/Ports/Impl/Response.cs index ac1b528ffd0af252bde21fe2a24f845fab9c323c..5302d1abd708509975bb264e892819f16be2deba 100644 --- a/VectoCore/VectoCore/Models/Connector/Ports/Impl/Response.cs +++ b/VectoCore/VectoCore/Models/Connector/Ports/Impl/Response.cs @@ -48,6 +48,8 @@ namespace TUGraz.VectoCore.Models.Connector.Ports.Impl public PerSecond EngineSpeed { get; set; } public Watt EnginePowerRequest { get; set; } + public Watt DynamicFullLoadPower { get; set; } + public Watt AngularGearPowerRequest { get; set; } public Watt ClutchPowerRequest { get; set; } public Watt GearboxPowerRequest { get; set; } @@ -75,7 +77,8 @@ namespace TUGraz.VectoCore.Models.Connector.Ports.Impl /// <summary> /// Response when a request was successful. /// </summary> - public class ResponseSuccess : AbstractResponse {} + public class ResponseSuccess : AbstractResponse { + } /// <summary> /// Response when the request resulted in an engine or gearbox overload. diff --git a/VectoCore/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs b/VectoCore/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs index 36ea2416b6e934360f40b902e6b6e43decb39f8a..7bfcdb22b2c3a4119825f322892530b95a15baaa 100644 --- a/VectoCore/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs +++ b/VectoCore/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs @@ -33,6 +33,7 @@ using System; using System.Linq; using TUGraz.VectoCommon.Exceptions; using TUGraz.VectoCommon.Models; +using TUGraz.VectoCommon.Utils; using TUGraz.VectoCore.Models.Simulation.Data; using TUGraz.VectoCore.Models.SimulationComponent; using TUGraz.VectoCore.Models.SimulationComponent.Data; @@ -138,7 +139,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl .AddComponent(new Brakes(container)) .AddComponent(new AxleGear(container, data.AxleGearData)) .AddComponent(data.AngularGearData != null ? new AngularGear(container, data.AngularGearData) : null) - .AddComponent(GetGearbox(container, data.GearboxData), data.Retarder, data.PTO, container); + .AddComponent(GetGearbox(container, data.GearboxData, data.EngineData.Inertia), data.Retarder, data.PTO, container); if (data.GearboxData.Type.ManualTransmission()) { powertrain = powertrain.AddComponent(new Clutch(container, data.EngineData)); } @@ -169,7 +170,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl .AddComponent(new Brakes(container)) .AddComponent(new AxleGear(container, data.AxleGearData)) .AddComponent(data.AngularGearData != null ? new AngularGear(container, data.AngularGearData) : null) - .AddComponent(GetGearbox(container, data.GearboxData), data.Retarder, data.PTO, container); + .AddComponent(GetGearbox(container, data.GearboxData, data.EngineData.Inertia), data.Retarder, data.PTO, container); if (data.GearboxData.Type.ManualTransmission()) { powertrain = powertrain.AddComponent(new Clutch(container, data.EngineData)); } @@ -196,7 +197,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl .AddComponent(new Brakes(container)) .AddComponent(new AxleGear(container, data.AxleGearData)) .AddComponent(data.AngularGearData != null ? new AngularGear(container, data.AngularGearData) : null) - .AddComponent(GetGearbox(container, data.GearboxData), data.Retarder, data.PTO, container); + .AddComponent(GetGearbox(container, data.GearboxData, data.EngineData.Inertia), data.Retarder, data.PTO, container); if (data.GearboxData.Type.ManualTransmission()) { powertrain = powertrain.AddComponent(new Clutch(container, data.EngineData)); } @@ -256,7 +257,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl return aux; } - private static IGearbox GetGearbox(IVehicleContainer container, GearboxData data) + private static IGearbox GetGearbox(IVehicleContainer container, GearboxData data, KilogramSquareMeter engineInertia) { IShiftStrategy strategy; switch (data.Type) { @@ -269,7 +270,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl case GearboxType.ATPowerSplit: case GearboxType.ATSerial: strategy = new ATShiftStrategy(data, container); - return new ATGearbox(container, data, strategy); + return new ATGearbox(container, data, strategy, engineInertia); default: throw new VectoSimulationException("Unknown Gearbox Type: {0}", data.Type); } diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TorqueConverterData.cs b/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TorqueConverterData.cs index 170b2f50f0ced831e85f893b8236d1a41e396c97..0626475a0286bb9f51e8ef38b810fd23c0c03f02 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TorqueConverterData.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TorqueConverterData.cs @@ -175,6 +175,39 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox } return GetOutTorque(inAngularVelocity, solutions.Max().SI<PerSecond>()); } + + public TorqueConverterOperatingPoint GetMaxPowerOperatingPoint(Watt maxPower, PerSecond prevInputSpeed, + PerSecond nextOutputSpeed, KilogramSquareMeter inertia, Second dt) + { + //var retVal = new TorqueConverterOperatingPoint { + // OutAngularVelocity = nextOutputSpeed + //}; + var solutions = new List<double>(); + var mpNorm = ReferenceSpeed.Value(); + + foreach (var segment in TorqueConverterEntries.Pairwise(Tuple.Create)) { + var mpEdge = Edge.Create(new Point(segment.Item1.SpeedRatio, segment.Item1.Torque.Value()), + new Point(segment.Item2.SpeedRatio, segment.Item2.Torque.Value())); + + var a = mpEdge.OffsetXY / mpNorm / mpNorm; + var b = inertia.Value() / 2 / dt.Value() + mpEdge.SlopeXY * nextOutputSpeed.Value() / mpNorm / mpNorm; + var c = 0; + var d = -inertia.Value() / 2 / dt.Value() * prevInputSpeed.Value() * prevInputSpeed.Value() - maxPower.Value(); + var sol = VectoMath.CubicEquationSolver(a, b, c, d); + + var selected = sol.Where(x => x > 0 && nextOutputSpeed / x >= mpEdge.P1.X && nextOutputSpeed / x < mpEdge.P2.X); + solutions.AddRange(selected); + } + + if (solutions.Count == 0) { + throw new VectoException( + "Failed to find operating point for maxPower {0}, prevInputSpeed {1}, nextOutputSpeed {2}", maxPower, + prevInputSpeed, nextOutputSpeed); + } + solutions.Sort(); + + return GetOutTorque(solutions.First().SI<PerSecond>(), nextOutputSpeed); + } } public class TorqueConverterOperatingPoint diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/ATGearbox.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/ATGearbox.cs index 13f4ba20f0e8f152ce4b393c8dc67e7a44e50bd4..bfae1be4cfd13a530d902f44997318dff1c17331 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/ATGearbox.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/ATGearbox.cs @@ -23,13 +23,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl public Second LastShift { get; private set; } - public ATGearbox(IVehicleContainer container, GearboxData gearboxModelData, IShiftStrategy strategy) + public ATGearbox(IVehicleContainer container, GearboxData gearboxModelData, IShiftStrategy strategy, KilogramSquareMeter engineInertia) : base(container, gearboxModelData) { Strategy = strategy; Strategy.Gearbox = this; LastShift = -double.MaxValue.SI<Second>(); - TorqueConverter = new TorqueConverter(this, Strategy, container, gearboxModelData.TorqueConverterData); + TorqueConverter = new TorqueConverter(this, Strategy, container, gearboxModelData.TorqueConverterData, engineInertia); } private IIdleController _idleController; diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs index 613672faa50d46ffefa798c1d79a2ac8ccb5be50..4c2e520c796dcfcd06b6b1bfbbe5e8b8e95b23e8 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs @@ -216,6 +216,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl DeltaFullLoad = deltaFull * avgEngineSpeed, DeltaDragLoad = deltaDrag * avgEngineSpeed, EnginePowerRequest = torqueOut * avgEngineSpeed, + DynamicFullLoadPower = dynamicFullLoadPower, AuxiliariesPowerDemand = auxTorqueDemand * avgEngineSpeed, EngineSpeed = angularVelocity, EngineMaxTorqueOut = @@ -252,6 +253,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl AbsTime = absTime, Delta = deltaFull * avgEngineSpeed, EnginePowerRequest = totalTorqueDemand * avgEngineSpeed, + DynamicFullLoadPower = dynamicFullLoadPower, Source = this, AuxiliariesPowerDemand = auxTorqueDemand * avgEngineSpeed, EngineSpeed = angularVelocity, @@ -265,6 +267,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl AbsTime = absTime, Delta = deltaDrag * avgEngineSpeed, EnginePowerRequest = totalTorqueDemand * avgEngineSpeed, + DynamicFullLoadPower = dynamicFullLoadPower, Source = this, AuxiliariesPowerDemand = auxTorqueDemand * avgEngineSpeed, EngineSpeed = angularVelocity, @@ -275,6 +278,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return new ResponseSuccess { EnginePowerRequest = totalTorqueDemand * avgEngineSpeed, + DynamicFullLoadPower = dynamicFullLoadPower, AuxiliariesPowerDemand = auxTorqueDemand * avgEngineSpeed, EngineSpeed = angularVelocity, Source = this diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/TorqueConverter.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/TorqueConverter.cs index de33055ce3846a10a49e95f4a6c2e3c53f7c799b..83c481351b1fd3a16e4872024a10bd4e499793f0 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/TorqueConverter.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/TorqueConverter.cs @@ -14,22 +14,24 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl public class TorqueConverter : StatefulVectoSimulationComponent<TorqueConverter.TorqueConverterComponentState>, ITnInPort, ITnOutPort { - protected ATGearbox Gearbox; + protected readonly ATGearbox Gearbox; - protected IShiftStrategy ShiftStrategy; + protected readonly IShiftStrategy ShiftStrategy; protected TorqueConverterData ModelData; + private KilogramSquareMeter EngineInertia; //protected bool SearchingTcOperatingPoint; public ITnOutPort NextComponent { protected internal get; set; } public TorqueConverter(ATGearbox gearbox, IShiftStrategy shiftStrategy, IVehicleContainer container, - TorqueConverterData tcData) : base(container) + TorqueConverterData tcData, KilogramSquareMeter engineInertia) : base(container) { Gearbox = gearbox; ShiftStrategy = shiftStrategy; ModelData = tcData; + EngineInertia = engineInertia; } public void Connect(ITnOutPort other) @@ -52,12 +54,17 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { if (dryRun) { var dryOperatingPoint = FindOperatingPoint(outTorque, outAngularVelocity); - var deltaTorqueConverter = (outTorque - dryOperatingPoint.OutTorque) * - (PreviousState.OutAngularVelocity + dryOperatingPoint.OutAngularVelocity) / 2.0; - // operatingPoint.inAngularVelocity is for sure between engine idle speed and max TC speed var engineResponse = (ResponseDryRun)NextComponent.Request(absTime, dt, dryOperatingPoint.InTorque, dryOperatingPoint.InAngularVelocity, true); + + //var dryOperatingPoint = FindOperatingPoint(outTorque, outAngularVelocity); + var deltaTorqueConverter = (outTorque - dryOperatingPoint.OutTorque) * + (PreviousState.OutAngularVelocity + dryOperatingPoint.OutAngularVelocity) / 2.0; + //// operatingPoint.inAngularVelocity is for sure between engine idle speed and max TC speed + //var engineResponse = + // (ResponseDryRun)NextComponent.Request(absTime, dt, dryOperatingPoint.InTorque, dryOperatingPoint.InAngularVelocity, + // true); var deltaEngine = (engineResponse.DeltaFullLoad > 0 ? engineResponse.DeltaFullLoad : 0.SI<Watt>()) + (engineResponse.DeltaDragLoad < 0 ? -engineResponse.DeltaDragLoad : 0.SI<Watt>()); if (deltaTorqueConverter.IsEqual(0) && deltaEngine.IsEqual(0)) { @@ -68,15 +75,19 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl TorqueConverterOperatingPoint = dryOperatingPoint }; } - if (engineResponse.DeltaFullLoad > 0 || engineResponse.DeltaDragLoad < 0) { - // engine is overloaded with current operating point, reduce torque... - dryOperatingPoint = - ModelData.GetOutTorqueAndSpeed( - outTorque > 0 ? engineResponse.EngineMaxTorqueOut : engineResponse.EngineDragTorque, - dryOperatingPoint.InAngularVelocity, null); - } - + dryOperatingPoint = GetMaxPowerOperatingPoint(dt, outAngularVelocity, engineResponse); + engineResponse = (ResponseDryRun)NextComponent.Request(absTime, dt, dryOperatingPoint.InTorque, + dryOperatingPoint.InAngularVelocity, true); + + //if (engineResponse.DeltaFullLoad > 0 || engineResponse.DeltaDragLoad < 0) + //{ + // // engine is overloaded with current operating point, reduce torque... + // dryOperatingPoint = + // ModelData.GetOutTorqueAndSpeed( + // outTorque > 0 ? engineResponse.EngineMaxTorqueOut : engineResponse.EngineDragTorque, + // dryOperatingPoint.InAngularVelocity, null); + //} var delta = (outTorque - dryOperatingPoint.OutTorque) * (PreviousState.OutAngularVelocity + dryOperatingPoint.OutAngularVelocity) / 2.0; //deltaTorqueConverter.Value() * (deltaEngine.IsEqual(0) ? 1 : deltaEngine.Value()); @@ -110,6 +121,23 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return retVal; } + private TorqueConverterOperatingPoint GetMaxPowerOperatingPoint(Second dt, PerSecond outAngularVelocity, + ResponseDryRun engineResponse) + { + try { + var operatingPoint = + ModelData.GetMaxPowerOperatingPoint(engineResponse.DynamicFullLoadPower - engineResponse.AuxiliariesPowerDemand, + DataBus.EngineSpeed, outAngularVelocity, EngineInertia, dt); + if (operatingPoint.InAngularVelocity.IsGreater(DataBus.EngineRatedSpeed)) { + operatingPoint = ModelData.GetOutTorque(DataBus.EngineRatedSpeed, outAngularVelocity); + } + return operatingPoint; + } catch (VectoException ve) { + Log.Error(ve, "failed to find torque converter operating point for MaxPower"); + throw; + } + } + protected internal TorqueConverterOperatingPoint FindOperatingPoint(NewtonMeter outTorque, PerSecond outAngularVelocity) { @@ -120,7 +148,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl operatingPoint.InAngularVelocity); } if (operatingPoint.InAngularVelocity.IsGreater(DataBus.EngineRatedSpeed)) { - //ModelData.TorqueConverterSpeedLimit)) { operatingPoint = ModelData.GetOutTorque(DataBus.EngineRatedSpeed, outAngularVelocity); } return operatingPoint; diff --git a/VectoCore/VectoCoreTest/Integration/ATPowerTrain.cs b/VectoCore/VectoCoreTest/Integration/ATPowerTrain.cs index 1c3c96f7808cc39c14595cf48fce984924e96ed6..cb5971d3e6210eaa1d152a60bdbf414c5c420204 100644 --- a/VectoCore/VectoCoreTest/Integration/ATPowerTrain.cs +++ b/VectoCore/VectoCoreTest/Integration/ATPowerTrain.cs @@ -70,7 +70,7 @@ namespace TUGraz.VectoCore.Tests.Integration .AddComponent(new Brakes(container)) .AddComponent(new AxleGear(container, axleGearData)) .AddComponent(new DummyRetarder(container)) - .AddComponent(new ATGearbox(container, gearboxData, new ATShiftStrategy(gearboxData, container))) + .AddComponent(new ATGearbox(container, gearboxData, new ATShiftStrategy(gearboxData, container), engineData.Inertia)) .AddComponent(engine); var aux = new EngineAuxiliary(container); diff --git a/VectoCore/VectoCoreTest/Models/SimulationComponent/ATGearboxTest.cs b/VectoCore/VectoCoreTest/Models/SimulationComponent/ATGearboxTest.cs index 32533e33e92d5531e93729ef5876465b26fb87be..8f62fa8781c58895e69be14ce963eb9e57726f2c 100644 --- a/VectoCore/VectoCoreTest/Models/SimulationComponent/ATGearboxTest.cs +++ b/VectoCore/VectoCoreTest/Models/SimulationComponent/ATGearboxTest.cs @@ -38,10 +38,10 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent public void TestATGearInitialize(double vehicleSpeed, double torque, int expectedGear) { var vehicleContainer = new MockVehicleContainer(); //(ExecutionMode.Engineering); - vehicleContainer.Engine = new CombustionEngine(vehicleContainer, - MockSimulationDataFactory.CreateEngineDataFromFile(EngineDataFile)); + var engineData = MockSimulationDataFactory.CreateEngineDataFromFile(EngineDataFile); + vehicleContainer.Engine = new CombustionEngine(vehicleContainer,engineData); var gearboxData = MockSimulationDataFactory.CreateGearboxDataFromFile(GearboxDataFile, EngineDataFile, false); - var gearbox = new ATGearbox(vehicleContainer, gearboxData, new ATShiftStrategy(gearboxData, vehicleContainer)); + var gearbox = new ATGearbox(vehicleContainer, gearboxData, new ATShiftStrategy(gearboxData, vehicleContainer), engineData.Inertia); vehicleContainer.VehicleSpeed = vehicleSpeed.KMPHtoMeterPerSecond();