diff --git a/VectoCore/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs b/VectoCore/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs index e4bd04ff55049946e558643966dc23c74f5128c7..75be63d9981355c518ce4107aec937e6760c97b6 100644 --- a/VectoCore/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs +++ b/VectoCore/VectoCore/Models/Simulation/Impl/PowertrainBuilder.cs @@ -104,7 +104,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl } var container = new VehicleContainer(ExecutionMode.Engineering, _modData, _sumWriter) { RunData = data }; - var gearbox = new CycleGearbox(container, data.GearboxData); + var gearbox = new CycleGearbox(container, data.GearboxData, data.EngineData.Inertia); // PWheelCycle --> AxleGear --> CycleClutch --> Engine <-- Aux var powertrain = new PWheelCycle(container, data.Cycle, data.AxleGearData.AxleGear.Ratio, @@ -170,13 +170,15 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl .AddComponent(new Brakes(container)) .AddComponent(new AxleGear(container, data.AxleGearData)) .AddComponent(data.AngledriveData != null ? new Angledrive(container, data.AngledriveData) : null) - .AddComponent(GetGearbox(container, data.GearboxData, data.EngineData.Inertia), data.Retarder, data.PTO, container); + .AddComponent(new CycleGearbox(container, data.GearboxData, data.EngineData.Inertia)); if (data.GearboxData.Type.ManualTransmission()) { powertrain = powertrain.AddComponent(new Clutch(container, data.EngineData)); } powertrain.AddComponent(new CombustionEngine(container, data.EngineData)) .AddAuxiliaries(container, data); + _modData.HasTorqueConverter = data.GearboxData.Type.AutomaticTransmission(); + return container; } diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/CycleGearbox.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/CycleGearbox.cs index 8b8b15cb5149c3b8cb190dd3d4c3618e7fb44f6f..a42808dae12651e995ffeffa6b84194fadceccde 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/CycleGearbox.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/CycleGearbox.cs @@ -44,15 +44,17 @@ using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { - public class CycleGearbox : AbstractGearbox<GearboxState> + public class CycleGearbox : AbstractGearbox<CycleGearbox.CycleGearboxState> { protected bool? TorqueConverterActive; protected internal TorqueConverterData TorqueConverter; + private readonly KilogramSquareMeter _engineInertia; - public CycleGearbox(IVehicleContainer container, GearboxData gearboxModelData) + public CycleGearbox(IVehicleContainer container, GearboxData gearboxModelData, KilogramSquareMeter engineInertia) : base(container, gearboxModelData) { + _engineInertia = engineInertia; if (!gearboxModelData.Type.AutomaticTransmission()) { return; } @@ -95,12 +97,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl } } else { inTorque = 0.SI<NewtonMeter>(); - inAngularVelocity = 0.RPMtoRad(); + inAngularVelocity = DataBus.EngineIdleSpeed; } PreviousState.SetState(inTorque, inAngularVelocity, outTorque, outAngularVelocity); PreviousState.InertiaTorqueLossOut = 0.SI<NewtonMeter>(); PreviousState.Gear = Gear; + var response = NextComponent.Initialize(inTorque, inAngularVelocity); response.GearboxPowerRequest = inTorque * inAngularVelocity; return response; @@ -136,9 +139,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl } - return Gear == 0 + var retVal = Gear == 0 ? RequestDisengaged(absTime, dt, outTorque, outAngularVelocity, dryRun) : RequestEngaged(absTime, dt, outTorque, outAngularVelocity, dryRun); + + retVal.GearboxPowerRequest = outTorque * outAngularVelocity; + return retVal; + } /// <summary> @@ -155,7 +162,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { var avgOutAngularVelocity = (PreviousState.OutAngularVelocity + outAngularVelocity) / 2.0; var inTorqueLossResult = ModelData.Gears[Gear].LossMap.GetTorqueLoss(avgOutAngularVelocity, outTorque); - var inTorque = outTorque / ModelData.Gears[Gear].Ratio - inTorqueLossResult.Value; + var inTorque = outTorque / ModelData.Gears[Gear].Ratio + inTorqueLossResult.Value; CurrentState.TorqueLossResult = inTorqueLossResult; var inAngularVelocity = outAngularVelocity * ModelData.Gears[Gear].Ratio; @@ -193,6 +200,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl // end critical section if (TorqueConverter != null && TorqueConverterActive != null && TorqueConverterActive.Value) { + CurrentState.TorqueConverterActive = true; return RequestTorqueConverter(absTime, dt, outTorque, outAngularVelocity); } @@ -244,33 +252,26 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl PerSecond outAngularVelocity) { var dryOperatingPoint = FindOperatingPoint(outTorque, outAngularVelocity); + var engineResponse = + (ResponseDryRun)NextComponent.Request(absTime, dt, dryOperatingPoint.InTorque, dryOperatingPoint.InAngularVelocity, + true); + 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)) { - return new ResponseDryRun { - Source = this, - DeltaFullLoad = 0.SI<Watt>(), - DeltaDragLoad = 0.SI<Watt>(), - TorqueConverterOperatingPoint = dryOperatingPoint - }; - } - if (engineResponse.DeltaFullLoad > 0 || engineResponse.DeltaDragLoad < 0) { - // engine is overloaded with current operating point, reduce torque... - dryOperatingPoint = - TorqueConverter.FindOperatingPoint( - outTorque > 0 ? engineResponse.EngineMaxTorqueOut : engineResponse.EngineDragTorque, - dryOperatingPoint.InAngularVelocity, null); - } + + dryOperatingPoint = outTorque.IsGreater(0) && DataBus.BrakePower.IsEqual(0) + ? GetMaxPowerOperatingPoint(dt, outAngularVelocity, engineResponse) + : GetDragPowerOperatingPoint(dt, outAngularVelocity, engineResponse); + engineResponse = (ResponseDryRun)NextComponent.Request(absTime, dt, dryOperatingPoint.InTorque, + dryOperatingPoint.InAngularVelocity, true); + var delta = (outTorque - dryOperatingPoint.OutTorque) * (PreviousState.OutAngularVelocity + dryOperatingPoint.OutAngularVelocity) / 2.0; + //deltaTorqueConverter.Value() * (deltaEngine.IsEqual(0) ? 1 : deltaEngine.Value()); return new ResponseDryRun() { Source = this, DeltaFullLoad = delta, @@ -338,8 +339,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl throw new VectoException("Invalid operating point, inAngularVelocity below engine's idle speed: {0}", operatingPoint.InAngularVelocity); } - if (operatingPoint.InAngularVelocity.IsGreater(TorqueConverter.TorqueConverterSpeedLimit)) { - operatingPoint = TorqueConverter.FindOperatingPoint(TorqueConverter.TorqueConverterSpeedLimit, outAngularVelocity); + if (operatingPoint.InAngularVelocity.IsGreater(DataBus.EngineRatedSpeed)) { + operatingPoint = TorqueConverter.FindOperatingPoint(DataBus.EngineRatedSpeed, outAngularVelocity); } return operatingPoint; } catch (VectoException ve) { @@ -349,10 +350,53 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl } } + private TorqueConverterOperatingPoint GetDragPowerOperatingPoint(Second dt, PerSecond outAngularVelocity, + ResponseDryRun engineResponse) + { + try { + var operatingPoint = + ModelData.TorqueConverterData.FindOperatingPointForPowerDemand( + engineResponse.DragPower - engineResponse.AuxiliariesPowerDemand, + DataBus.EngineSpeed, outAngularVelocity, _engineInertia, dt); + if (operatingPoint.InAngularVelocity.IsGreater(DataBus.EngineRatedSpeed)) { + operatingPoint = ModelData.TorqueConverterData.FindOperatingPoint(DataBus.EngineRatedSpeed, outAngularVelocity); + } + if (operatingPoint.InAngularVelocity.IsSmaller(DataBus.EngineIdleSpeed)) { + operatingPoint = ModelData.TorqueConverterData.FindOperatingPoint(DataBus.EngineIdleSpeed, outAngularVelocity); + } + return operatingPoint; + } catch (VectoException ve) { + Log.Error(ve, "failed to find torque converter operating point for DragPower {0}", engineResponse.DragPower); + //throw; + return ModelData.TorqueConverterData.FindOperatingPoint(engineResponse.EngineSpeed, outAngularVelocity); + } + } + + private TorqueConverterOperatingPoint GetMaxPowerOperatingPoint(Second dt, PerSecond outAngularVelocity, + ResponseDryRun engineResponse) + { + try { + var operatingPoint = + ModelData.TorqueConverterData.FindOperatingPointForPowerDemand( + engineResponse.DynamicFullLoadPower - engineResponse.AuxiliariesPowerDemand, + DataBus.EngineSpeed, outAngularVelocity, _engineInertia, dt); + if (operatingPoint.InAngularVelocity.IsGreater(DataBus.EngineRatedSpeed)) { + operatingPoint = ModelData.TorqueConverterData.FindOperatingPoint(DataBus.EngineRatedSpeed, outAngularVelocity); + } + return operatingPoint; + } catch (VectoException ve) { + Log.Error(ve, "failed to find torque converter operating point for MaxPower {0}", + engineResponse.DynamicFullLoadPower); + throw; + } + } + protected override void DoWriteModalResults(IModalDataContainer container) { container[ModalResultField.Gear] = Gear; - + if (ModelData.Type.AutomaticTransmission()) { + container[ModalResultField.TC_Locked] = !CurrentState.TorqueConverterActive; + } var avgInAngularSpeed = Gear != 0 ? (PreviousState.OutAngularVelocity + CurrentState.OutAngularVelocity) / 2.0 * ModelData.Gears[Gear].Ratio : 0.RPMtoRad(); @@ -387,5 +431,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl } #endregion + + public class CycleGearboxState : GearboxState + { + public bool TorqueConverterActive; + } } } \ No newline at end of file diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/TorqueConverter.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/TorqueConverter.cs index e2e86577474746df296ec6ca8ccc88aff99a12fe..5840f0311cf7fa07bafb3a132b03ed78d6aaa114 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/TorqueConverter.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/TorqueConverter.cs @@ -19,7 +19,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl protected readonly IShiftStrategy ShiftStrategy; protected TorqueConverterData ModelData; - private KilogramSquareMeter EngineInertia; + private readonly KilogramSquareMeter _engineInertia; //protected bool SearchingTcOperatingPoint; @@ -31,7 +31,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl Gearbox = gearbox; ShiftStrategy = shiftStrategy; ModelData = tcData; - EngineInertia = engineInertia; + _engineInertia = engineInertia; } public void Connect(ITnOutPort other) @@ -58,23 +58,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl (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)) { - // return new ResponseDryRun { - // Source = this, - // DeltaFullLoad = 0.SI<Watt>(), - // DeltaDragLoad = 0.SI<Watt>(), - // TorqueConverterOperatingPoint = dryOperatingPoint - // }; - //} dryOperatingPoint = outTorque.IsGreater(0) && DataBus.BrakePower.IsEqual(0) ? GetMaxPowerOperatingPoint(dt, outAngularVelocity, engineResponse) @@ -82,14 +70,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl 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()); @@ -134,7 +115,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl try { var operatingPoint = ModelData.FindOperatingPointForPowerDemand(engineResponse.DragPower - engineResponse.AuxiliariesPowerDemand, - DataBus.EngineSpeed, outAngularVelocity, EngineInertia, dt); + DataBus.EngineSpeed, outAngularVelocity, _engineInertia, dt); if (operatingPoint.InAngularVelocity.IsGreater(DataBus.EngineRatedSpeed)) { operatingPoint = ModelData.FindOperatingPoint(DataBus.EngineRatedSpeed, outAngularVelocity); } @@ -154,8 +135,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { try { var operatingPoint = - ModelData.FindOperatingPointForPowerDemand(engineResponse.DynamicFullLoadPower - engineResponse.AuxiliariesPowerDemand, - DataBus.EngineSpeed, outAngularVelocity, EngineInertia, dt); + ModelData.FindOperatingPointForPowerDemand( + engineResponse.DynamicFullLoadPower - engineResponse.AuxiliariesPowerDemand, + DataBus.EngineSpeed, outAngularVelocity, _engineInertia, dt); if (operatingPoint.InAngularVelocity.IsGreater(DataBus.EngineRatedSpeed)) { operatingPoint = ModelData.FindOperatingPoint(DataBus.EngineRatedSpeed, outAngularVelocity); } diff --git a/VectoCore/VectoCoreTest/Models/Simulation/PwheelModeTests.cs b/VectoCore/VectoCoreTest/Models/Simulation/PwheelModeTests.cs index 76c98f6cede854e66e3e98be51d2d415f2979e5d..2cbb49582202e2642fc97763b327d6d3ddcd13da 100644 --- a/VectoCore/VectoCoreTest/Models/Simulation/PwheelModeTests.cs +++ b/VectoCore/VectoCoreTest/Models/Simulation/PwheelModeTests.cs @@ -72,7 +72,7 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation var gearbox = new CycleGearbox(container, new GearboxData { Gears = new Dictionary<uint, GearData> { { 1, new GearData { Ratio = 2.0 } }, { 2, new GearData { Ratio = 3.5 } } } - }); + }, 0.SI<KilogramSquareMeter>()); var cycle = new PWheelCycle(container, drivingCycle, 2.3, gearbox.ModelData.Gears.ToDictionary(g => g.Key, g => g.Value.Ratio));