From fead95003a6ef346e4eb4cc9a63002d78e072736 Mon Sep 17 00:00:00 2001 From: "VKMTHD\\haraldmartini" <harald.martini@student.tugraz.at> Date: Fri, 3 Mar 2023 08:26:58 +0100 Subject: [PATCH] add limits to parallelhybrid strategy --- .../DeclarationDataAdapterHeavyLorry.cs | 31 ++- .../IDeclarationDataAdapter.cs | 12 ++ .../HybridStrategyParameterDataAdapter.cs | 178 +++++++++++++++++- ...tionModeHeavyLorryRunDataFactory_Hybrid.cs | 7 +- 4 files changed, 216 insertions(+), 12 deletions(-) diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/HeavyLorry/DeclarationDataAdapterHeavyLorry.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/HeavyLorry/DeclarationDataAdapterHeavyLorry.cs index 3e03afd4ea..48b2a8800f 100644 --- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/HeavyLorry/DeclarationDataAdapterHeavyLorry.cs +++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/HeavyLorry/DeclarationDataAdapterHeavyLorry.cs @@ -105,8 +105,23 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.HeavyLorry throw new NotImplementedException(); } + public virtual HybridStrategyParameters CreateHybridStrategy(BatterySystemData runDataBatteryData, SuperCapData runDataSuperCapData, + Kilogram vehicleMass, VectoRunData.OvcHevMode ovcMode, LoadingType loading, VehicleClass vehicleClass, MissionType missionType) + { + throw new NotImplementedException(); + } + public virtual HybridStrategyParameters CreateHybridStrategy(BatterySystemData runDataBatteryData, - SuperCapData runDataSuperCapData, Kilogram vehicleMass, VectoRunData.OvcHevMode ovcMode, LoadingType loading, VehicleClass vehicleClass, MissionType missionType) + SuperCapData runDataSuperCapData, + Kilogram vehicleMass, + VectoRunData.OvcHevMode ovcMode, + LoadingType loading, + VehicleClass vehicleClass, + MissionType missionType, + TableData boostingLimitations, + GearboxData gearboxData, + CombustionEngineData engineData, + ArchitectureID archId) { throw new NotImplementedException(); } @@ -408,9 +423,17 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.HeavyLorry } public override HybridStrategyParameters CreateHybridStrategy(BatterySystemData runDataBatteryData, - SuperCapData runDataSuperCapData, Kilogram vehicleMass, VectoRunData.OvcHevMode ovcMode, LoadingType loading, VehicleClass vehicleClass, MissionType missionType) - { - return _hybridStrategyDataAdapter.CreateHybridStrategyParameters(runDataBatteryData, runDataSuperCapData, ovcMode, loading, vehicleClass, missionType); + SuperCapData runDataSuperCapData, Kilogram vehicleMass, VectoRunData.OvcHevMode ovcMode, + LoadingType loading, VehicleClass vehicleClass, MissionType missionType, TableData boostingLimitations, + GearboxData gearboxData, CombustionEngineData engineData, ArchitectureID archID) + { + return _hybridStrategyDataAdapter.CreateHybridStrategyParameters( + batterySystemData: runDataBatteryData, + superCap: runDataSuperCapData, + ovcMode: ovcMode, + loading: loading, + vehicleClass: vehicleClass, + missionType: missionType, archID, engineData, gearboxData, boostingLimitations); } #endregion diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/IDeclarationDataAdapter.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/IDeclarationDataAdapter.cs index 9e49993179..56edb1623b 100644 --- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/IDeclarationDataAdapter.cs +++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/IDeclarationDataAdapter.cs @@ -80,6 +80,18 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter SuperCapData CreateSuperCapData(IElectricStorageSystemDeclarationInputData componentsElectricStorage); HybridStrategyParameters CreateHybridStrategy(BatterySystemData runDataBatteryData, SuperCapData runDataSuperCapData, Kilogram vehicleMass, VectoRunData.OvcHevMode ovcMode, LoadingType loading, VehicleClass vehicleClass, MissionType missionType); + + HybridStrategyParameters CreateHybridStrategy(BatterySystemData runDataBatteryData, + SuperCapData runDataSuperCapData, + Kilogram vehicleMass, + VectoRunData.OvcHevMode ovcMode, + LoadingType loading, + VehicleClass vehicleClass, + MissionType missionType, + TableData boostingLimitations, + GearboxData gearboxData, + CombustionEngineData engineData, + ArchitectureID archId); ShiftStrategyParameters CreateDummyGearshiftStrategy(); } diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/StrategyDataAdapter/HybridStrategyParameterDataAdapter.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/StrategyDataAdapter/HybridStrategyParameterDataAdapter.cs index 62ee2023e0..b81ad5070f 100644 --- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/StrategyDataAdapter/HybridStrategyParameterDataAdapter.cs +++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/SimulationComponents/StrategyDataAdapter/HybridStrategyParameterDataAdapter.cs @@ -1,9 +1,12 @@ using System; using System.Collections.Generic; +using System.Linq; using NLog.Targets; using TUGraz.VectoCommon.Exceptions; +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.Data; using TUGraz.VectoCore.Models.SimulationComponent.Data; @@ -15,13 +18,167 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.SimulationComponen { public abstract class HybridStrategyDataAdapter{ - - } - - public class ParallelHybridStrategyParameterDataAdapter : HybridStrategyDataAdapter + protected internal static Dictionary<GearshiftPosition, VehicleMaxPropulsionTorque> CreateMaxPropulsionTorque( + ArchitectureID archId, CombustionEngineData engineData, GearboxData gearboxData, TableData boostingLimitations) + { + + // engine data contains full-load curves already cropped with max gearbox torque and max ICE torque (vehicle level) + + var maxBoostingTorque = boostingLimitations; + var offset = maxBoostingTorque == null ? null : MaxBoostingTorqueReader.Create(maxBoostingTorque); + var belowIdle = offset?.FullLoadEntries.Where(x => x.MotorSpeed < engineData.IdleSpeed).ToList(); + + var retVal = new Dictionary<GearshiftPosition, VehicleMaxPropulsionTorque>(); + + var isP3OrP4Hybrid = archId.IsOneOf(ArchitectureID.P3, ArchitectureID.P4); + //vehicleInputData.Components.ElectricMachines.Entries.Select(x => x.Position) + // .Any(x => x == PowertrainPosition.HybridP3 || x == PowertrainPosition.HybridP4); + foreach (var key in engineData.FullLoadCurves.Keys) + { + if (key == 0) + { + continue; + } + if (maxBoostingTorque == null) + { + if (gearboxData.Gears[key].MaxTorque == null) + { + continue; + } + // don't know what to do... + // idea 1: apply gearbox limit for whole speed range + // idea 2: use em max torque as boosting limitation + var gbxLimit = new[] { + new VehicleMaxPropulsionTorque.FullLoadEntry() + { MotorSpeed = 0.RPMtoRad(), FullDriveTorque = gearboxData.Gears[key].MaxTorque }, + new VehicleMaxPropulsionTorque.FullLoadEntry() { + MotorSpeed = engineData.FullLoadCurves[0].N95hSpeed * 1.1, + FullDriveTorque = gearboxData.Gears[key].MaxTorque + } + }.ToList(); + retVal[new GearshiftPosition(key, true)] = new VehicleMaxPropulsionTorque(gbxLimit); + continue; + } + + // case boosting limit is defined, gearbox limit can be defined or not (handled in Intersect method) + + // entries contains ICE full-load curve with the boosting torque added. handles ICE speeds below idle + var entries = belowIdle.Select(fullLoadEntry => new VehicleMaxPropulsionTorque.FullLoadEntry() + { MotorSpeed = fullLoadEntry.MotorSpeed, FullDriveTorque = fullLoadEntry.FullDriveTorque }) + .Concat( + engineData.FullLoadCurves[key].FullLoadEntries.Where(x => x.EngineSpeed > engineData.IdleSpeed) + .Select(fullLoadCurveEntry => + new VehicleMaxPropulsionTorque.FullLoadEntry() + { + MotorSpeed = fullLoadCurveEntry.EngineSpeed, + FullDriveTorque = fullLoadCurveEntry.TorqueFullLoad + + VectoMath.Max( + offset?.FullLoadDriveTorque(fullLoadCurveEntry.EngineSpeed), + 0.SI<NewtonMeter>()) + })) + .Concat( + new[] { engineData.IdleSpeed, engineData.IdleSpeed - 0.1.RPMtoRad() }.Select(x => + new VehicleMaxPropulsionTorque.FullLoadEntry() + { + MotorSpeed = x, + FullDriveTorque = engineData.FullLoadCurves[0].FullLoadStationaryTorque(x) + + VectoMath.Max(offset?.FullLoadDriveTorque(x), + 0.SI<NewtonMeter>()) + })) + .OrderBy(x => x.MotorSpeed).ToList(); + + // if no gearbox limit is defined, MaxTorque is null; + // in case of P3 or P4, do not apply gearbox limit to propulsion limit as ICE is already cropped with max torque + var gearboxTorqueLimit = isP3OrP4Hybrid ? null : gearboxData.Gears[key].MaxTorque; + retVal[new GearshiftPosition(key, true)] = new VehicleMaxPropulsionTorque(IntersectMaxPropulsionTorqueCurve(entries, gearboxTorqueLimit)); + + } + + return retVal; + } + /// <summary> + /// Intersects max torque curve. + /// </summary> + /// <param name="maxTorqueEntries"></param> + /// <param name="maxTorque"></param> + /// <returns>A combined EngineFullLoadCurve with the minimum full load torque over all inputs curves.</returns> + internal static IList<VehicleMaxPropulsionTorque.FullLoadEntry> IntersectMaxPropulsionTorqueCurve(IList<VehicleMaxPropulsionTorque.FullLoadEntry> maxTorqueEntries, NewtonMeter maxTorque) + { + if (maxTorque == null) + { + return maxTorqueEntries; + } + + var entries = new List<VehicleMaxPropulsionTorque.FullLoadEntry>(); + var firstEntry = maxTorqueEntries.First(); + if (firstEntry.FullDriveTorque < maxTorque) + { + entries.Add(maxTorqueEntries.First()); + } + else + { + entries.Add(new VehicleMaxPropulsionTorque.FullLoadEntry + { + MotorSpeed = firstEntry.MotorSpeed, + FullDriveTorque = maxTorque, + }); + } + foreach (var entry in maxTorqueEntries.Pairwise(Tuple.Create)) + { + if (entry.Item1.FullDriveTorque <= maxTorque && entry.Item2.FullDriveTorque <= maxTorque) + { + // segment is below maxTorque line -> use directly + entries.Add(entry.Item2); + } + else if (entry.Item1.FullDriveTorque > maxTorque && entry.Item2.FullDriveTorque > maxTorque) + { + // segment is above maxTorque line -> add limited entry + entries.Add(new VehicleMaxPropulsionTorque.FullLoadEntry + { + MotorSpeed = entry.Item2.MotorSpeed, + FullDriveTorque = maxTorque, + }); + } + else + { + // segment intersects maxTorque line -> add new entry at intersection + var edgeFull = Edge.Create( + new Point(entry.Item1.MotorSpeed.Value(), entry.Item1.FullDriveTorque.Value()), + new Point(entry.Item2.MotorSpeed.Value(), entry.Item2.FullDriveTorque.Value())); + + var intersectionX = (maxTorque.Value() - edgeFull.OffsetXY) / edgeFull.SlopeXY; + if (!entries.Any(x => x.MotorSpeed.IsEqual(intersectionX)) && !intersectionX.IsEqual(entry.Item2.MotorSpeed.Value())) + { + entries.Add(new VehicleMaxPropulsionTorque.FullLoadEntry + { + MotorSpeed = intersectionX.SI<PerSecond>(), + FullDriveTorque = maxTorque, + }); + } + + entries.Add(new VehicleMaxPropulsionTorque.FullLoadEntry + { + MotorSpeed = entry.Item2.MotorSpeed, + FullDriveTorque = entry.Item2.FullDriveTorque > maxTorque ? maxTorque : entry.Item2.FullDriveTorque, + + }); + } + } + + + return entries; + } + } + + public class ParallelHybridStrategyParameterDataAdapter : HybridStrategyDataAdapter { - public HybridStrategyParameters CreateHybridStrategyParameters(BatterySystemData batterySystemData, - SuperCapData superCap, VectoRunData.OvcHevMode ovcMode, LoadingType loading, VehicleClass vehicleClass, MissionType missionType) + public HybridStrategyParameters CreateHybridStrategyParameters( + BatterySystemData batterySystemData, + SuperCapData superCap, + VectoRunData.OvcHevMode ovcMode, + LoadingType loading, + VehicleClass vehicleClass, + MissionType missionType, ArchitectureID archID, CombustionEngineData engineData, GearboxData gearboxData, TableData boostingLimitations) { if (batterySystemData == null && superCap == null) { return null; @@ -57,6 +214,8 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.SimulationComponen result.MinICEOnTime = 10.SI<Second>(); result.ICEStartPenaltyFactor = 0.1; result.CostFactorSOCExponent = 1; + result.MaxPropulsionTorque = + CreateMaxPropulsionTorque(archID, engineData, gearboxData, boostingLimitations); if (ovcMode == VectoRunData.OvcHevMode.ChargeSustaining) { result.EquivalenceFactor = @@ -73,7 +232,12 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter.SimulationComponen return result; } - } + + + + + + } public class SerialHybridStrategyParameterDataAdapter : HybridStrategyDataAdapter { diff --git a/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationMode/HeavyLorryRunDataFactory/DeclarationModeHeavyLorryRunDataFactory_Hybrid.cs b/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationMode/HeavyLorryRunDataFactory/DeclarationModeHeavyLorryRunDataFactory_Hybrid.cs index 641476b3c1..458b7e1449 100644 --- a/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationMode/HeavyLorryRunDataFactory/DeclarationModeHeavyLorryRunDataFactory_Hybrid.cs +++ b/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationMode/HeavyLorryRunDataFactory/DeclarationModeHeavyLorryRunDataFactory_Hybrid.cs @@ -268,7 +268,12 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl.DeclarationMode.HeavyLorryRunDa runData.BatteryData.CalculateAverageVoltage(), runData.GearboxData.GearList); runData.HybridStrategyParameters = - DataAdapter.CreateHybridStrategy(runData.BatteryData, runData.SuperCapData, runData.VehicleData.TotalVehicleMass, ovcMode, loading.Key, runData.VehicleData.VehicleClass, mission.MissionType); + DataAdapter.CreateHybridStrategy(runData.BatteryData, + runData.SuperCapData, + runData.VehicleData.TotalVehicleMass, + ovcMode, loading.Key, + runData.VehicleData.VehicleClass, + mission.MissionType, vehicle.BoostingLimitations, runData.GearboxData, runData.EngineData, vehicle.ArchitectureID); if (ovcMode != VectoRunData.OvcHevMode.NotApplicable) { -- GitLab