From 7930a5a7764fc90a50d8020788a5c83a53228cdf Mon Sep 17 00:00:00 2001 From: Markus Quaritsch <markus.quaritsch@tugraz.at> Date: Thu, 22 Jul 2021 14:38:35 +0200 Subject: [PATCH] finetuning PEV shift strategy --- VectoCommon/VectoCommon/Models/IResponse.cs | 1 + .../AbstractSimulationDataAdapter.cs | 13 +- .../Models/Declaration/DeclarationData.cs | 28 +- .../Data/ShiftStrategyParameters.cs | 6 +- .../Data/ElectricMotor/ElectricMotorData.cs | 2 +- .../ElectricMotorFullLoadCurve.cs | 10 +- .../Impl/BatteryElectricMotorController.cs | 2 +- .../SimulationComponent/Impl/ElectricMotor.cs | 5 + .../Impl/PEVAMTShiftStrategy.cs | 909 ++++-------------- .../BatteryElectric/BatteryElectricTest.cs | 20 +- .../Models/Declaration/ShiftPolygonTest.cs | 73 +- .../GenericVehicleB2/3speedEV.vgbx | 54 ++ .../GenericVehicleB2/BEV_ENG_3speed.vecto | 45 + VectoCore/VectoCoreTest/VectoCoreTest.csproj | 6 + 14 files changed, 409 insertions(+), 765 deletions(-) create mode 100644 VectoCore/VectoCoreTest/TestData/BatteryElectric/GenericVehicleB2/3speedEV.vgbx create mode 100644 VectoCore/VectoCoreTest/TestData/BatteryElectric/GenericVehicleB2/BEV_ENG_3speed.vecto diff --git a/VectoCommon/VectoCommon/Models/IResponse.cs b/VectoCommon/VectoCommon/Models/IResponse.cs index c3ddf1fdcb..ad0e0d1d5d 100644 --- a/VectoCommon/VectoCommon/Models/IResponse.cs +++ b/VectoCommon/VectoCommon/Models/IResponse.cs @@ -168,6 +168,7 @@ namespace TUGraz.VectoCommon.Models public NewtonMeter MaxDriveTorqueEM { get; set; } public NewtonMeter MaxRecuperationTorqueEM { get; set; } public NewtonMeter TorqueRequestEmMap { get; set; } + public bool DeRatingActive { get; set; } } diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/AbstractSimulationDataAdapter.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/AbstractSimulationDataAdapter.cs index e57bba3134..584a23ad1f 100644 --- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/AbstractSimulationDataAdapter.cs +++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/AbstractSimulationDataAdapter.cs @@ -368,11 +368,14 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter } // create new full-load curve with values closest to zero. - return new ElectricMotorFullLoadCurve(motorSpeeds.OrderBy(x => x.Value()).Distinct().Select(x => new ElectricMotorFullLoadCurve.FullLoadEntry() { - MotorSpeed = x, - FullDriveTorque = VectoMath.Max(fullLoadCurve.FullLoadDriveTorque(x), maxTorqueCurve.FullLoadDriveTorque(x)), - FullGenerationTorque = VectoMath.Min(fullLoadCurve.FullGenerationTorque(x), maxTorqueCurve.FullGenerationTorque(x)), - }).ToList()); + return new ElectricMotorFullLoadCurve(motorSpeeds.OrderBy(x => x.Value()).Distinct().Select(x => + new ElectricMotorFullLoadCurve.FullLoadEntry() { + MotorSpeed = x, + FullDriveTorque = VectoMath.Max(fullLoadCurve.FullLoadDriveTorque(x), + maxTorqueCurve.FullLoadDriveTorque(x)), + FullGenerationTorque = VectoMath.Min(fullLoadCurve.FullGenerationTorque(x), + maxTorqueCurve.FullGenerationTorque(x)), + }).ToList()); } diff --git a/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs b/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs index ee8c57bc53..a60b1be4fd 100644 --- a/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs +++ b/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs @@ -622,7 +622,7 @@ namespace TUGraz.VectoCore.Models.Declaration public static ShiftPolygon ComputeElectricMotorShiftPolygon(int gearIdx, ElectricMotorFullLoadCurve fullLoadCurve, double emRatio, IList<ITransmissionInputData> gears, - double axlegearRatio, Meter dynamicTyreRadius) + double axlegearRatio, Meter dynamicTyreRadius, PerSecond downshiftMaxSpeed = null) { if (gears.Count < 2) { throw new VectoException("ComputeShiftPolygon needs at least 2 gears. {0} gears given.", gears.Count); @@ -631,7 +631,7 @@ namespace TUGraz.VectoCore.Models.Declaration var downShift = new List<ShiftPolygon.ShiftPolygonEntry>(); var upShift = new List<ShiftPolygon.ShiftPolygonEntry>(); if (gearIdx > 0) { - var nMax = fullLoadCurve.NP80low; + var nMax = downshiftMaxSpeed ?? fullLoadCurve.NP80low; var nMin = 0.1 * fullLoadCurve.RatedSpeed; downShift.AddRange(DownshiftLineDrive(fullLoadCurve, nMin, nMax)); @@ -673,22 +673,26 @@ namespace TUGraz.VectoCore.Models.Declaration nMin)); } else { - if (downShiftPoints.Min(x => x.X) > nMin) { + retVal.Add( + new ShiftPolygon.ShiftPolygonEntry( + fullLoadCurve.MaxDriveTorque * 1.1, + nMax)); + if (downShiftPoints.Max(x => x.X) < nMax) { retVal.Add( new ShiftPolygon.ShiftPolygonEntry( - fullLoadCurve.FullLoadDriveTorque(nMin) * ShiftPolygonEngineFldMargin, + fullLoadCurve.FullLoadDriveTorque(nMax) * ShiftPolygonEngineFldMargin, nMax)); } retVal.AddRange( downShiftPoints.Select( x => new ShiftPolygon.ShiftPolygonEntry( - x.Y.SI<NewtonMeter>() * ShiftPolygonEngineFldMargin, x.X.SI<PerSecond>()))); - if (downShiftPoints.Max(x => x.X) < nMax) { + x.Y.SI<NewtonMeter>(), x.X.SI<PerSecond>())).OrderByDescending(x => x.AngularSpeed.Value())); + if (downShiftPoints.Min(x => x.X) > nMin) { retVal.Add( new ShiftPolygon.ShiftPolygonEntry( - fullLoadCurve.FullLoadDriveTorque(nMax) * ShiftPolygonEngineFldMargin, - nMax)); + fullLoadCurve.FullLoadDriveTorque(nMin) * ShiftPolygonEngineFldMargin, + nMin)); } } @@ -724,19 +728,23 @@ namespace TUGraz.VectoCore.Models.Declaration retVal.Add( new ShiftPolygon.ShiftPolygonEntry( fullLoadCurve.FullGenerationTorque(nMin) * ShiftPolygonEngineFldMargin, - nMax)); + nMin)); } retVal.AddRange( downShiftPoints.Select( x => new ShiftPolygon.ShiftPolygonEntry( - x.Y.SI<NewtonMeter>() * ShiftPolygonEngineFldMargin, x.X.SI<PerSecond>()))); + x.Y.SI<NewtonMeter>(), x.X.SI<PerSecond>()))); if (downShiftPoints.Max(x => x.X) < nMax) { retVal.Add( new ShiftPolygon.ShiftPolygonEntry( fullLoadCurve.FullGenerationTorque(nMax) * ShiftPolygonEngineFldMargin, nMax)); } + retVal.Add( + new ShiftPolygon.ShiftPolygonEntry( + fullLoadCurve.MaxGenerationTorque * 1.1, + nMax)); } return retVal; diff --git a/VectoCore/VectoCore/Models/Simulation/Data/ShiftStrategyParameters.cs b/VectoCore/VectoCore/Models/Simulation/Data/ShiftStrategyParameters.cs index 03638744c9..bc6264d349 100644 --- a/VectoCore/VectoCore/Models/Simulation/Data/ShiftStrategyParameters.cs +++ b/VectoCore/VectoCore/Models/Simulation/Data/ShiftStrategyParameters.cs @@ -10,7 +10,8 @@ namespace TUGraz.VectoCore.Models.Simulation.Data { { public ShiftStrategyParameters() { - TargetSpeedBrakeNorm = 0.7; + PEV_TargetSpeedBrakeNorm = 0.7; + PEV_DeRatedDownshiftSpeedFactor = 1; } public MeterPerSecond StartVelocity { get; internal set; } @@ -106,6 +107,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Data { public double[] LoadStageThresoldsUp { get; set; } public double[] LoadStageThresoldsDown { get; set; } public double[][] ShiftSpeedsTCToLocked { get; set; } - public double TargetSpeedBrakeNorm { get; set; } + public double PEV_TargetSpeedBrakeNorm { get; set; } + public double PEV_DeRatedDownshiftSpeedFactor { get; set; } } } \ No newline at end of file diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Data/ElectricMotor/ElectricMotorData.cs b/VectoCore/VectoCore/Models/SimulationComponent/Data/ElectricMotor/ElectricMotorData.cs index 56c6427664..e2dbfde141 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Data/ElectricMotor/ElectricMotorData.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Data/ElectricMotor/ElectricMotorData.cs @@ -55,7 +55,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data get { return _maxSpeed ?? (_maxSpeed = VoltageLevels - .Min(v => v.EfficiencyMap.MaxSpeed)); + .Min(v => VectoMath.Min(v.EfficiencyMap.MaxSpeed, v.FullLoadCurve.MaxSpeed))); } } diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Data/ElectricMotor/ElectricMotorFullLoadCurve.cs b/VectoCore/VectoCore/Models/SimulationComponent/Data/ElectricMotor/ElectricMotorFullLoadCurve.cs index 930d5e84b8..011f82f9c7 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Data/ElectricMotor/ElectricMotorFullLoadCurve.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Data/ElectricMotor/ElectricMotorFullLoadCurve.cs @@ -107,7 +107,15 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.ElectricMotor { { var max = new Tuple<PerSecond, Watt>(0.SI<PerSecond>(), 0.SI<Watt>()); for (var idx = 1; idx < FullLoadEntries.Count; idx++) { - var currentMax = FindMaxPower(FullLoadEntries[idx - 1], FullLoadEntries[idx]); + var entry2 = FullLoadEntries[idx]; + if (FullLoadEntries[idx].MotorSpeed > MaxSpeed) { + entry2 = new FullLoadEntry() { + MotorSpeed = MaxSpeed, + FullDriveTorque = FullLoadDriveTorque(MaxSpeed), + FullGenerationTorque = FullGenerationTorque(MaxSpeed) + }; + } + var currentMax = FindMaxPower(FullLoadEntries[idx - 1], entry2); if (currentMax.Item2 > max.Item2) { max = currentMax; } diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/BatteryElectricMotorController.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/BatteryElectricMotorController.cs index dbdf8745f5..9a3609cfb9 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/BatteryElectricMotorController.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/BatteryElectricMotorController.cs @@ -32,7 +32,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { ? 0.SI<NewtonMeter>() : Formulas.InertiaPower(currOutAngularVelocity, prevOutAngularVelocity, ElectricMotorData.Inertia, dt) / avgSpeed; //var dragTorque = ElectricMotorData.DragCurve.Lookup() - return (-inertiaTorqueLoss).LimitTo(maxDriveTorque, maxRecuperationTorque); + return (-inertiaTorqueLoss); //.LimitTo(maxDriveTorque, maxRecuperationTorque); } if (DataBus.DriverInfo.DrivingAction == DrivingAction.Coast || DataBus.DriverInfo.DrivingAction == DrivingAction.Roll) { diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/ElectricMotor.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/ElectricMotor.cs index 264ba3812f..17da629f52 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/ElectricMotor.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/ElectricMotor.cs @@ -289,6 +289,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl IResponse retVal = null; if (NextComponent == null) { + if (electricSupplyResponse.MaxPowerDrive.IsEqual(0.SI<Watt>(), 100.SI<Watt>())) { + retVal = new ResponseBatteryEmpty(this, electricSupplyResponse); + return retVal; + } // electric motor only var remainingPower = inTorqueDt * avgDtSpeed; if (dryRun) { @@ -344,6 +348,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl retVal.ElectricMotor.MaxRecuperationTorqueEM = maxRecuperationTorqueEm; retVal.ElectricMotor.AngularVelocity = avgEmSpeed; retVal.ElectricMotor.AvgDrivetrainSpeed = avgDtSpeed; + retVal.ElectricMotor.DeRatingActive = DeRatingActive; retVal.ElectricMotor.TorqueRequest = outTorque; retVal.ElectricMotor.TorqueRequestEmMap = emTorqueMap; diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/PEVAMTShiftStrategy.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/PEVAMTShiftStrategy.cs index bdaaa0702b..b0f63c7da7 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/PEVAMTShiftStrategy.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/PEVAMTShiftStrategy.cs @@ -6,6 +6,7 @@ using TUGraz.VectoCommon.InputData; using TUGraz.VectoCommon.Models; using TUGraz.VectoCommon.Utils; using TUGraz.VectoCore.Configuration; +using TUGraz.VectoCore.InputData.Reader.DataObjectAdapter; using TUGraz.VectoCore.Models.Connector.Ports.Impl; using TUGraz.VectoCore.Models.Declaration; using TUGraz.VectoCore.Models.Simulation; @@ -38,9 +39,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl private SI TransmissionRatio; private ShiftStrategyParameters GearshiftParams; private GearList GearList; + private Dictionary<uint, ShiftPolygon> DeRatedShiftpolygons; - public static string Name => "AMT - EffShift (BEV)"; + public static string Name => "AMT - EffShift (BEV)"; protected bool DriveOffStandstill { get; set; } @@ -48,6 +50,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl public PEVAMTShiftStrategy(IVehicleContainer dataBus) { var runData = dataBus.RunData; + shiftStrategyParameters = runData.GearshiftParameters; if (runData.VehicleData == null) { return; } @@ -64,16 +67,20 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl TransmissionRatio = runData.AxleGearData.AxleGear.Ratio * (runData.AngledriveData?.Angledrive.Ratio ?? 1.0) / runData.VehicleData.DynamicTyreRadius; - //var minEngineSpeed = (runData.EngineData.FullLoadCurves[0].RatedSpeed - runData.EngineData.IdleSpeed) * - // Constants.SimulationSettings.ClutchClosingSpeedNorm + runData.EngineData.IdleSpeed; + //var minEngineSpeed = (runData.EngineData.FullLoadCurves[0].RatedSpeed - runData.EngineData.IdleSpeed) * + // Constants.SimulationSettings.ClutchClosingSpeedNorm + runData.EngineData.IdleSpeed; - shiftStrategyParameters = runData.GearshiftParameters; + if (shiftStrategyParameters == null) { throw new VectoException("Parameters for shift strategy missing!"); } SetupVelocityDropPreprocessor(dataBus); - } + + DeRatedShiftpolygons = CalculateDeratedShiftLines(runData.ElectricMachinesData.First(x => x.Item1 == PowertrainPosition.BatteryElectricE2).Item2, + runData.GearboxData.InputData.Gears, runData.VehicleData.DynamicTyreRadius, + runData.AxleGearData.AxleGear.Ratio, runData.GearboxData.Type); + } private void SetupVelocityDropPreprocessor(IVehicleContainer dataBus) { @@ -106,11 +113,60 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl IList<ITransmissionInputData> gearboxGears, CombustionEngineData engineData, double axlegearRatio, Meter dynamicTyreRadius, ElectricMotorData electricMotorData = null) { - return DeclarationData.Gearbox.ComputeElectricMotorShiftPolygon(i, electricMotorData.EfficiencyData.VoltageLevels.First().FullLoadCurve, electricMotorData.RatioADC, gearboxGears, axlegearRatio, dynamicTyreRadius); + return ComputeDeclarationShiftPolygon(i, gearboxGears, axlegearRatio, dynamicTyreRadius, electricMotorData, + null); + } + + + public ShiftPolygon ComputeDeclarationShiftPolygon(int i, + IList<ITransmissionInputData> gearboxGears, double axlegearRatio, + Meter dynamicTyreRadius, + ElectricMotorData electricMotorData , PerSecond downshiftMaxSpeed ) + { + return DeclarationData.Gearbox.ComputeElectricMotorShiftPolygon(i, + electricMotorData.EfficiencyData.VoltageLevels.First().FullLoadCurve, electricMotorData.RatioADC, + gearboxGears, axlegearRatio, dynamicTyreRadius, downshiftMaxSpeed); } #endregion + protected internal Dictionary<uint, ShiftPolygon> CalculateDeratedShiftLines(ElectricMotorData em, + IList<ITransmissionInputData> gearData, Meter rDyn, double axleGearRatio, GearboxType gearboxType) + { + var retVal = new Dictionary<uint, ShiftPolygon>(); + var emFld = em.EfficiencyData.VoltageLevels.First().FullLoadCurve; + var contTqFld = new ElectricMotorFullLoadCurve(new List<ElectricMotorFullLoadCurve.FullLoadEntry>() { + new ElectricMotorFullLoadCurve.FullLoadEntry() { + MotorSpeed = 0.RPMtoRad(), + FullDriveTorque = -em.ContinuousTorque, + FullGenerationTorque = em.ContinuousTorque + }, + new ElectricMotorFullLoadCurve.FullLoadEntry() { + MotorSpeed = 1.1 * emFld.MaxSpeed, + FullDriveTorque = -em.ContinuousTorque, + FullGenerationTorque = em.ContinuousTorque + } + }); + var limitedFld = AbstractSimulationDataAdapter.IntersectEMFullLoadCurves(emFld, contTqFld); + var limitedEm = new ElectricMotorData() { + EfficiencyData = new VoltageLevelData() { + VoltageLevels = new List<ElectricMotorVoltageLevelData>() { + new ElectricMotorVoltageLevelData() { + FullLoadCurve = limitedFld + } + } + } + }; + for (var i = 0u; i < gearData.Count; i++) { + var shiftPolygon = ComputeDeclarationShiftPolygon((int)i, + gearData, axleGearRatio, + rDyn, limitedEm, shiftStrategyParameters.PEV_DeRatedDownshiftSpeedFactor * emFld.RatedSpeed); + retVal[i + 1] = shiftPolygon; + } + + return retVal; + } + #region Implementation of IShiftStrategy public bool ShiftRequired(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, NewtonMeter inTorque, @@ -205,7 +261,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { var nextGear = currentGear; // upshift - if (IsAboveUpShiftCurve(currentGear, inTorque, inAngularVelocity)) { + if (IsAboveUpShiftCurve(currentGear, inTorque, inAngularVelocity, r.ElectricMotor.DeRatingActive)) { nextGear = GearList.Successor(currentGear); while (GearList.HasSuccessor(nextGear)) { @@ -224,7 +280,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl var reserve = 1 - inTorque / maxTorque; if (reserve >= 0 /*ModelData.TorqueReserve */ && - IsAboveDownShiftCurve(nextGear, inTorque, inAngularVelocity)) { + IsAboveDownShiftCurve(nextGear, inTorque, inAngularVelocity, r.ElectricMotor.DeRatingActive)) { continue; } @@ -236,30 +292,40 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return nextGear; } - protected virtual GearshiftPosition CheckEarlyUpshift(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, GearshiftPosition currentGear, IResponse response1) + protected virtual GearshiftPosition CheckEarlyUpshift(Second absTime, Second dt, NewtonMeter outTorque, + PerSecond outAngularVelocity, GearshiftPosition currentGear, IResponse resp) { - var estimatedVelocityPostShift = VelocityDropData.Interpolate(DataBus.VehicleInfo.VehicleSpeed, DataBus.DrivingCycleInfo.RoadGradient ?? 0.SI<Radian>()); - if (!estimatedVelocityPostShift.IsGreater(DeclarationData.GearboxTCU.MIN_SPEED_AFTER_TRACTION_INTERRUPTION)) { + var estimatedVelocityPostShift = VelocityDropData.Interpolate(DataBus.VehicleInfo.VehicleSpeed, + DataBus.DrivingCycleInfo.RoadGradient ?? 0.SI<Radian>()); + if (!estimatedVelocityPostShift.IsGreater(DeclarationData.GearboxTCU.MIN_SPEED_AFTER_TRACTION_INTERRUPTION) + ) { return currentGear; } var vDrop = DataBus.VehicleInfo.VehicleSpeed - estimatedVelocityPostShift; - var vehicleSpeedPostShift = DataBus.VehicleInfo.VehicleSpeed - vDrop * shiftStrategyParameters.VelocityDropFactor; + var vehicleSpeedPostShift = + DataBus.VehicleInfo.VehicleSpeed - vDrop * shiftStrategyParameters.VelocityDropFactor; + + var totalTransmissionRatio = + DataBus.ElectricMotorInfo(PowertrainPosition.BatteryElectricE2).ElectricMotorSpeed / + DataBus.VehicleInfo.VehicleSpeed; - var totalTransmissionRatio = DataBus.ElectricMotorInfo(PowertrainPosition.BatteryElectricE2).ElectricMotorSpeed / DataBus.VehicleInfo.VehicleSpeed; - var results = new List<Tuple<GearshiftPosition, double>>(); - foreach (var tryNextGear in GearList.IterateGears(GearList.Successor(currentGear), GearList.Successor(currentGear, (uint)shiftStrategyParameters.AllowedGearRangeFC))) { + foreach (var tryNextGear in GearList.IterateGears(GearList.Successor(currentGear), + GearList.Successor(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; - if (IsBelowDownShiftCurve(tryNextGear, inTorque, inAngularVelocity)) { + if (IsBelowDownShiftCurve(tryNextGear, inTorque, inAngularVelocity, resp.ElectricMotor.DeRatingActive)) { continue; } - var estimatedEngineSpeed = (vehicleSpeedPostShift * (totalTransmissionRatio / GearboxModelData.Gears[currentGear.Gear].Ratio * GearboxModelData.Gears[tryNextGear.Gear].Ratio)).Cast<PerSecond>(); + var estimatedEngineSpeed = (vehicleSpeedPostShift * (totalTransmissionRatio / + GearboxModelData.Gears[currentGear.Gear].Ratio * + GearboxModelData.Gears[tryNextGear.Gear].Ratio)) + .Cast<PerSecond>(); if (estimatedEngineSpeed.IsSmaller(shiftStrategyParameters.MinEngineSpeedPostUpshift)) { continue; } @@ -293,9 +359,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl } return currentGear; - //return fcUpshiftPossible - // ? currentGear - // : base.CheckEarlyUpshift(absTime, dt, outTorque, outAngularVelocity, currentGear, response1); } @@ -311,10 +374,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return currentGear; } + if (response.ElectricMotor.DeRatingActive) { + + } // check with shiftline if (response.ElectricMotor.TorqueRequestEmMap != null && IsBelowDownShiftCurve(currentGear, response.ElectricMotor.TorqueRequestEmMap, - response.ElectricMotor.AngularVelocity)) { + response.ElectricMotor.AngularVelocity, response.ElectricMotor.DeRatingActive)) { if (DataBus.DriverInfo.DriverBehavior == DrivingBehavior.Braking) { var brakingGear = SelectBrakingGear(currentGear, response); @@ -322,6 +388,31 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl } var nextGear = GearList.Predecessor(currentGear); + + while (GearList.HasPredecessor(nextGear)) { + // check skip gears + nextGear = GearList.Predecessor(nextGear); + var resp = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, nextGear); + + inAngularVelocity = resp.ElectricMotor.AngularVelocity; + inTorque = resp.ElectricMotor.PowerRequest / inAngularVelocity; + + var maxTorque = VectoMath.Min(-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; + + if (reserve >= 0 /*ModelData.TorqueReserve */ && + IsBelowDownShiftCurve(nextGear, inTorque, inAngularVelocity, resp.ElectricMotor.DeRatingActive)) { + continue; + } + + nextGear = GearList.Successor(nextGear); + break; + } + return nextGear; } @@ -353,7 +444,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl var ratedSpeed = VoltageLevels.VoltageLevels.First().FullLoadCurve.RatedSpeed; var maxSpeedNorm = VoltageLevels.MaxSpeed / ratedSpeed; - var targetMotor = (shiftStrategyParameters.TargetSpeedBrakeNorm * (maxSpeedNorm - 1) + 1) * ratedSpeed; + var targetMotor = (shiftStrategyParameters.PEV_TargetSpeedBrakeNorm * (maxSpeedNorm - 1) + 1) * ratedSpeed; if (candidates.Any(x => x.Value > targetMotor && x.Value < VoltageLevels.MaxSpeed)) { var best = candidates.Where(x => x.Value > targetMotor && x.Value < VoltageLevels.MaxSpeed) @@ -365,21 +456,25 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return retVal; } - protected virtual GearshiftPosition CheckEarlyDownshift(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, GearshiftPosition currentGear, IResponse response1) + protected virtual GearshiftPosition CheckEarlyDownshift(Second absTime, Second dt, NewtonMeter outTorque, + PerSecond outAngularVelocity, GearshiftPosition currentGear, IResponse resp) { - var estimatedVelocityPostShift = VelocityDropData.Interpolate(DataBus.VehicleInfo.VehicleSpeed, DataBus.DrivingCycleInfo.RoadGradient ?? 0.SI<Radian>()); - if (!estimatedVelocityPostShift.IsGreater(DeclarationData.GearboxTCU.MIN_SPEED_AFTER_TRACTION_INTERRUPTION)) { + var estimatedVelocityPostShift = VelocityDropData.Interpolate(DataBus.VehicleInfo.VehicleSpeed, + DataBus.DrivingCycleInfo.RoadGradient ?? 0.SI<Radian>()); + if (!estimatedVelocityPostShift.IsGreater(DeclarationData.GearboxTCU.MIN_SPEED_AFTER_TRACTION_INTERRUPTION) + ) { return currentGear; } var results = new List<Tuple<GearshiftPosition, double>>(); - foreach (var tryNextGear in GearList.IterateGears(GearList.Predecessor(currentGear), GearList.Predecessor(currentGear, (uint)shiftStrategyParameters.AllowedGearRangeFC))) { + 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; - if (IsAboveUpShiftCurve(tryNextGear, inTorque, inAngularVelocity)) { + if (IsAboveUpShiftCurve(tryNextGear, inTorque, inAngularVelocity, response.ElectricMotor.DeRatingActive)) { continue; } @@ -399,7 +494,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl : shiftStrategyParameters.RatingFactorCurrentGear; if (minFc.Item2.IsGreater(fcCurrent * ratingFactor)) { - return minFc.Item1; + return minFc.Item1; } return currentGear; @@ -460,7 +555,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl var inTorque = response.ElectricMotor.PowerRequest / inAngularSpeed; // if in shift curve and torque reserve is provided: return the current gear - if (!IsBelowDownShiftCurve(gear, inTorque, inAngularSpeed) && !IsAboveUpShiftCurve(gear, inTorque, inAngularSpeed)) { + if (!IsBelowDownShiftCurve(gear, inTorque, inAngularSpeed, false) && !IsAboveUpShiftCurve(gear, inTorque, inAngularSpeed, false)) { _nextGear = gear; return gear; } @@ -514,28 +609,47 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl } - protected bool IsBelowDownShiftCurve(GearshiftPosition gear, NewtonMeter inTorque, PerSecond inEngineSpeed) + protected bool IsBelowDownShiftCurve(GearshiftPosition gear, NewtonMeter inTorque, PerSecond inEngineSpeed, + bool deRatingActive) { if (!GearList.HasPredecessor(gear)) { return false; } - return IsBelowDownshiftCurve(GearboxModelData.Gears[gear.Gear].ShiftPolygon, inTorque, inEngineSpeed); + + var shiftPolygon = GetShiftpolygon(gear, deRatingActive); + return IsBelowDownshiftCurve(shiftPolygon, inTorque, inEngineSpeed); } - protected bool IsAboveDownShiftCurve(GearshiftPosition gear, NewtonMeter inTorque, PerSecond inEngineSpeed) + + + protected bool IsAboveDownShiftCurve(GearshiftPosition gear, NewtonMeter inTorque, PerSecond inEngineSpeed, + bool deRatingActive) { if (!GearList.HasPredecessor(gear)) { return true; } - return GearboxModelData.Gears[gear.Gear].ShiftPolygon.IsAboveDownshiftCurve(inTorque, inEngineSpeed); + var shiftPolygon = GetShiftpolygon(gear, deRatingActive); + + return IsAboveDownshiftCurve(shiftPolygon, inTorque, inEngineSpeed); } - protected bool IsAboveUpShiftCurve(GearshiftPosition gear, NewtonMeter inTorque, PerSecond inEngineSpeed) + protected bool IsAboveUpShiftCurve(GearshiftPosition gear, NewtonMeter inTorque, PerSecond inEngineSpeed, + bool deRatingActive) { if (!GearList.HasSuccessor(gear)) { return false; } - return GearboxModelData.Gears[gear.Gear].ShiftPolygon.IsAboveUpshiftCurve(inTorque, inEngineSpeed); + + var shiftPolygon = GetShiftpolygon(gear, deRatingActive); + return shiftPolygon.IsAboveUpshiftCurve(inTorque, inEngineSpeed); + } + + private ShiftPolygon GetShiftpolygon(GearshiftPosition gear, bool deRatingActive) + { + if (deRatingActive) { + return DeRatedShiftpolygons[gear.Gear]; + } + return GearboxModelData.Gears[gear.Gear].ShiftPolygon; } protected bool IsBelowDownshiftCurve(ShiftPolygon shiftPolygon, NewtonMeter emTorque, PerSecond emSpeed) @@ -554,6 +668,22 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return false; } + protected bool IsAboveDownshiftCurve(ShiftPolygon shiftPolygon, NewtonMeter emTorque, PerSecond emSpeed) + { + foreach (var entry in shiftPolygon.Downshift.Pairwise(Tuple.Create)) { + if (!emTorque.IsBetween(entry.Item1.Torque, entry.Item2.Torque)) { + continue; + } + + if (ShiftPolygon.IsRightOf(emSpeed, emTorque, entry)) { + + return true; + } + } + + return false; + } + public GearshiftPosition Engage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity) { while (GearList.HasSuccessor(_nextGear) && SpeedTooHighForEngine(_nextGear, outAngularVelocity)) { @@ -591,712 +721,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl public void WriteModalResults(IModalDataContainer container) { } #endregion - } - - - // ########################## - - public class PEVAMTShiftStrategy_OLD : LoggingObject, IShiftStrategy - { - protected readonly IDataBus DataBus; - protected readonly GearboxData GearboxModelData; - - protected Gearbox _gearbox; - protected GearshiftPosition _nextGear; - - private ShiftStrategyParameters shiftStrategyParameters; - protected readonly VelocityRollingLookup VelocityDropData = new VelocityRollingLookup(); - private SimplePowertrainContainer TestContainer; - private Gearbox TestContainerGbx; - private Kilogram vehicleMass; - private VoltageLevelData VoltageLevels; - private SI TransmissionRatio; - private ShiftStrategyParameters GearshiftParams; - private GearList GearList; - - public bool EarlyShiftUp { get; } - - public bool SkipGears { get; } - - public static string Name => "AMT - EffShift (BEV)"; - - public enum GearshiftTrigger - { - NoShift = 0, - GearshiftBlockedTimeDelay = -2, - GearshiftBlockedNotAccelerating = -4, - AboveUpshiftLine = 10, - BelowDownshiftLine = -10, - EfficiencyShift = 5, - EmergencyShift = 2 - } - - public GearshiftTrigger ShiftTrigger; - private Second ShiftDecisionTstmp = -double.MaxValue.SI<Second>(); - - protected bool DriveOffStandstill = false; - - public PEVAMTShiftStrategy_OLD(IVehicleContainer dataBus) - { - var runData = dataBus.RunData; - if (runData.VehicleData == null) { - return; - } - GearboxModelData = dataBus.RunData.GearboxData; - GearshiftParams = dataBus.RunData.GearshiftParameters; - GearList = GearboxModelData.GearList; - MaxStartGear = GearList.Reverse().First(); - - VoltageLevels = dataBus.RunData.ElectricMachinesData - .FirstOrDefault(x => x.Item1 == PowertrainPosition.BatteryElectricE2)?.Item2.EfficiencyData; - - DataBus = dataBus; - - EarlyShiftUp = true; - SkipGears = true; - - TransmissionRatio = runData.AxleGearData.AxleGear.Ratio * - (runData.AngledriveData?.Angledrive.Ratio ?? 1.0) / - runData.VehicleData.DynamicTyreRadius; - //var minEngineSpeed = (runData.EngineData.FullLoadCurves[0].RatedSpeed - runData.EngineData.IdleSpeed) * - // Constants.SimulationSettings.ClutchClosingSpeedNorm + runData.EngineData.IdleSpeed; - - shiftStrategyParameters = runData.GearshiftParameters; - vehicleMass = runData.VehicleData.TotalVehicleMass; - if (shiftStrategyParameters == null) { - throw new VectoException("Parameters for shift strategy missing!"); - } - SetupVelocityDropPreprocessor(dataBus); - } - - private void SetupVelocityDropPreprocessor(IVehicleContainer dataBus) - { - var runData = dataBus.RunData; - // MQ: 2019-11-29 - fuel used here has no effect as this is the modDatacontainer for the test-powertrain only! - var modData = new ModalDataContainer(runData, null, null); - var builder = new PowertrainBuilder(modData); - TestContainer = new SimplePowertrainContainer(runData); - builder.BuildSimplePowertrainE2(runData, TestContainer); - TestContainerGbx = TestContainer.GearboxCtl as Gearbox; - if (TestContainerGbx == null) { - throw new VectoException("Unknown gearboxtype: {0}", TestContainer.GearboxCtl.GetType().FullName); - } - // register pre-processors - var maxG = runData.Cycle.Entries.Max(x => Math.Abs(x.RoadGradientPercent.Value())) + 1; - var grad = Convert.ToInt32(maxG / 2) * 2; - if (grad == 0) { - grad = 2; - } - - dataBus.AddPreprocessor( - new VelocitySpeedGearshiftPreprocessorE2(VelocityDropData, runData.GearboxData.TractionInterruption, TestContainer, -grad, grad, 2)); - - } - - public bool ShiftRequired(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, - NewtonMeter inTorque, - PerSecond inAngularVelocity, GearshiftPosition gear, Second lastShiftTime, IResponse response) - { - CheckGearshiftRequired = true; - var retVal = DoCheckShiftRequired(absTime, dt, outTorque, outAngularVelocity, inTorque, inAngularVelocity, - gear, lastShiftTime, response); - CheckGearshiftRequired = false; - return retVal; - } - - private bool DoCheckShiftRequired(Second absTime, Second dt, NewtonMeter outTorque, - PerSecond outAngularVelocity, NewtonMeter inTorque, PerSecond inAngularVelocity, GearshiftPosition gear, - Second lastShiftTime, IResponse response) - { - // no shift when vehicle stands - if (DataBus.VehicleInfo.VehicleStopped) { - return false; - } - - if (DriveOffStandstill && - DataBus.VehicleInfo.VehicleSpeed.IsGreaterOrEqual(DataBus.DrivingCycleInfo.TargetSpeed)) { - DriveOffStandstill = false; - } - if (DriveOffStandstill && response.ElectricMotor.AngularVelocity.IsGreater(VoltageLevels.VoltageLevels.First().FullLoadCurve.NP80low)) { - DriveOffStandstill = false; - } - - if (DriveOffStandstill && response.ElectricMotor.TorqueRequestEmMap != null && - response.ElectricMotor.TorqueRequestEmMap.IsEqual(response.ElectricMotor.MaxDriveTorqueEM)) { - DriveOffStandstill = false; - } - - // emergency shift to not stall the engine ------------------------ - while (GearList.HasSuccessor(_nextGear) && - SpeedTooHighForEngine(_nextGear, inAngularVelocity / GearboxModelData.Gears[gear.Gear].Ratio)) { - _nextGear = GearList.Successor(_nextGear); - } - if (_nextGear != gear) { - SetShiftDecision(GearshiftTrigger.EmergencyShift, absTime); - return true; - } - - if (DriveOffStandstill) { - return false; - } - - // normal shift when all requirements are fullfilled ------------------ - var minimumShiftTimePassed = (lastShiftTime + GearshiftParams.TimeBetweenGearshifts).IsSmallerOrEqual(absTime); - if (!minimumShiftTimePassed) { - SetShiftDecision(GearshiftTrigger.GearshiftBlockedTimeDelay, absTime); - return false; - } - - _nextGear = CheckDownshift(absTime, dt, outTorque, outAngularVelocity, inTorque, inAngularVelocity, gear, response); - if (_nextGear != gear) { - return true; - } - - _nextGear = CheckUpshift(absTime, dt, outTorque, outAngularVelocity, inTorque, inAngularVelocity, gear, response); - - //if ((ModelData.Gears[_nextGear].Ratio * outAngularVelocity - DataBus.EngineIdleSpeed) / - // (DataBus.EngineRatedSpeed - DataBus.EngineIdleSpeed) < - // Constants.SimulationSettings.ClutchClosingSpeedNorm && _nextGear > 1) { - // _nextGear--; - //} - - return _nextGear != gear; - } - - protected virtual GearshiftPosition CheckUpshift(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, NewtonMeter inTorque, PerSecond inAngularVelocity, GearshiftPosition currentGear, IResponse response) - { - // if the driver's intention is _not_ to accelerate or drive along then don't upshift - if (DataBus.DriverInfo.DriverBehavior != DrivingBehavior.Accelerating && DataBus.DriverInfo.DriverBehavior != DrivingBehavior.Driving) { - SetShiftDecision(GearshiftTrigger.GearshiftBlockedNotAccelerating, absTime); - return currentGear; - } - if ((absTime - _gearbox.LastDownshift).IsSmaller(GearshiftParams.UpshiftAfterDownshiftDelay)) { - SetShiftDecision(GearshiftTrigger.GearshiftBlockedTimeDelay, absTime); - return currentGear; - } - var nextGear = DoCheckUpshift(absTime, dt, outTorque, outAngularVelocity, inTorque, inAngularVelocity, currentGear, response); - if (nextGear.Equals(currentGear)) { - return nextGear; - } - - // estimate acceleration for selected gear - if (EstimateAccelerationForGear(nextGear, outAngularVelocity).IsSmaller(GearshiftParams.UpshiftMinAcceleration)) { - // if less than 0.1 for next gear, don't shift - if (GearList.Distance(nextGear, currentGear) == 1) { - return currentGear; - } - // if a gear is skipped but acceleration is less than 0.1, try for next gear. if acceleration is still below 0.1 don't shift! - if (nextGear > currentGear && - EstimateAccelerationForGear(GearList.Successor(currentGear), outAngularVelocity) - .IsSmaller(GearshiftParams.UpshiftMinAcceleration)) { - return currentGear; - } - nextGear = GearList.Successor(currentGear); - } - - return nextGear; - } - - protected virtual GearshiftPosition DoCheckUpshift(Second absTime, Second dt, NewtonMeter outTorque, - PerSecond outAngularVelocity, NewtonMeter inTorque, PerSecond inAngularVelocity, - GearshiftPosition currentGear, IResponse response1) - { - // upshift - if (IsAboveUpShiftCurve(currentGear, inTorque, inAngularVelocity)) { - currentGear = GearList.Successor(currentGear); - - while (SkipGears && GearList.HasSuccessor(currentGear)) { - currentGear = GearList.Successor(currentGear); - var response = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, currentGear); - - inAngularVelocity = - response.ElectricMotor - .AngularVelocity; //ModelData.Gears[currentGear].Ratio * outAngularVelocity; - inTorque = response.ElectricMotor.PowerRequest / inAngularVelocity; - - var maxTorque = VectoMath.Min(-response.ElectricMotor.MaxDriveTorque, - !currentGear.Equals(GearList.First()) - ? GearboxModelData.Gears[currentGear.Gear].ShiftPolygon - .InterpolateDownshift(response.Engine.EngineSpeed) - : double.MaxValue.SI<NewtonMeter>()); - var reserve = 1 - inTorque / maxTorque; - - if (reserve >= 0 /*ModelData.TorqueReserve */ && - IsAboveDownShiftCurve(currentGear, inTorque, inAngularVelocity)) { - continue; - } - - currentGear = GearList.Predecessor(currentGear); - break; - } - } - - // early up shift to higher gear --------------------------------------- - if (EarlyShiftUp && GearList.HasSuccessor(currentGear)) { - currentGear = CheckEarlyUpshift(absTime, dt, outTorque, outAngularVelocity, currentGear, response1); - } - - return currentGear; - } - - protected virtual GearshiftPosition CheckEarlyUpshift(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, GearshiftPosition currentGear, IResponse response1) - { - //var minFcGear = currentGear; - //var minFc = double.MaxValue; - //IResponse minFCResponse = null; - //var fcCurrent = double.NaN; + #region Implementation of IShiftPolygonCalculator - //var fcUpshiftPossible = true; + + #endregion + } - // no eff-shift if torque demand is close to ICE drag load - //if (response1.Engine.TorqueOutDemand.IsSmaller(DeclarationData.GearboxTCU.DragMarginFactor * fld[currentGear].DragLoadStationaryTorque(response1.Engine.EngineSpeed))) { - // return currentGear; - //} - - var estimatedVelocityPostShift = VelocityDropData.Interpolate(DataBus.VehicleInfo.VehicleSpeed, DataBus.DrivingCycleInfo.RoadGradient ?? 0.SI<Radian>()); - if (!estimatedVelocityPostShift.IsGreater(DeclarationData.GearboxTCU.MIN_SPEED_AFTER_TRACTION_INTERRUPTION)) { - return currentGear; - } - - var vDrop = DataBus.VehicleInfo.VehicleSpeed - estimatedVelocityPostShift; - var vehicleSpeedPostShift = DataBus.VehicleInfo.VehicleSpeed - vDrop * shiftStrategyParameters.VelocityDropFactor; - - var totalTransmissionRatio = DataBus.ElectricMotorInfo(PowertrainPosition.BatteryElectricE2).ElectricMotorSpeed / DataBus.VehicleInfo.VehicleSpeed; - //var totalTransmissionRatio = outAngularVelocity / DataBus.VehicleSpeed; - - var results = new List<Tuple<GearshiftPosition, double>>(); - foreach (var tryNextGear in GearList.IterateGears(GearList.Successor(currentGear), GearList.Successor(currentGear, (uint)shiftStrategyParameters.AllowedGearRangeFC))) { - - //if (tryNextGear > GearboxModelData.Gears.Keys.Max() - // /*|| !(ModelData.Gears[tryNextGear].Ratio < shiftStrategyParameters.RatioEarlyUpshiftFC)*/) { - // continue; - //} - - //fcUpshiftPossible = true; - - //var response = RequestDryRunWithGear(absTime, dt, vehicleSpeedPostShift, DataBus.DriverAcceleration, tryNextGear); - var response = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, tryNextGear); - - var inAngularVelocity = GearboxModelData.Gears[tryNextGear.Gear].Ratio * outAngularVelocity; - var inTorque = response.ElectricMotor.PowerRequest / inAngularVelocity; - - // if next gear supplied enough power reserve: take it - // otherwise take - if (IsBelowDownShiftCurve(tryNextGear, inTorque, inAngularVelocity)) { - continue; - } - - var estimatedEngineSpeed = (vehicleSpeedPostShift * (totalTransmissionRatio / GearboxModelData.Gears[currentGear.Gear].Ratio * GearboxModelData.Gears[tryNextGear.Gear].Ratio)).Cast<PerSecond>(); - if (estimatedEngineSpeed.IsSmaller(shiftStrategyParameters.MinEngineSpeedPostUpshift)) { - continue; - } - - //var pNextGearMax = DataBus.Engine Info.EngineStationaryFullPower(estimatedEngineSpeed); - - //if (!response.Engine.PowerRequest.IsSmaller(pNextGearMax)) { - // continue; - //} - - var fullLoadPower = -response.ElectricMotor.MaxDriveTorque * response.ElectricMotor.AngularVelocity; - var reserve = 1 - response.ElectricMotor.PowerRequest / fullLoadPower; - - //var reserve = 1 - response.EngineTorqueDemandTotal / response.EngineStationaryFullLoadTorque; - - - //if (double.IsNaN(fcCurrent)) { - // //var responseCurrent = RequestDryRunWithGear(absTime, dt, DataBus.VehicleSpeed, DataBus.DriverAcceleration, currentGear); - // var responseCurrent = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, currentGear); - // fcCurrent = GetFCRating(responseCurrent); - //} - - var fcNext = GetFCRating(response); - results.Add(Tuple.Create(tryNextGear, fcNext)); - - //if (reserve < GearshiftParams.TorqueReserve || - // !fcNext.IsGreater(fcCurrent * shiftStrategyParameters.RatingFactorCurrentGear) || !fcNext.IsSmaller(minFc)) { - // continue; - //} - - //minFcGear = tryNextGear; - //minFc = fcNext; - //minFCResponse = response; - } - - if (results.Count == 0) { - return currentGear; - } - - var responseCurrent = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, currentGear); - var fcCurrent = GetFCRating(responseCurrent); - - var minFc = results.MinBy(x => x.Item2); - - var ratingFactor = outTorque < 0 - ? 1 / shiftStrategyParameters.RatingFactorCurrentGear - : shiftStrategyParameters.RatingFactorCurrentGear; - - if (minFc.Item2.IsGreater(fcCurrent * ratingFactor)) { - return minFc.Item1; - } - - return currentGear; - //return fcUpshiftPossible - // ? currentGear - // : base.CheckEarlyUpshift(absTime, dt, outTorque, outAngularVelocity, currentGear, response1); - } - - - private double GetFCRating(ResponseDryRun response)//PerSecond engineSpeed, NewtonMeter tqCurrent) - { - var currentGear = response.Gearbox.Gear; - - var maxGenTorque = VectoMath.Min(GearboxModelData.Gears[currentGear.Gear].MaxTorque, response.ElectricMotor.MaxRecuperationTorque); - var maxDriveTorque = GearboxModelData.Gears[currentGear.Gear].MaxTorque != null - ? VectoMath.Max(-GearboxModelData.Gears[currentGear.Gear].MaxTorque, response.ElectricMotor.MaxDriveTorque) - : response.ElectricMotor.MaxDriveTorque; - - var tqCurrent = (response.ElectricMotor.ElectricMotorPowerMech / response.ElectricMotor.AngularVelocity); - if (!tqCurrent.IsBetween(maxDriveTorque, maxGenTorque)) { - return double.NaN; - } - var engineSpeed = response.ElectricMotor.AngularVelocity; - - - var fcCurRes = VoltageLevels.LookupElectricPower(DataBus.BatteryInfo.InternalVoltage, engineSpeed, tqCurrent, true); - if (fcCurRes.Extrapolated) { - Log.Warn( - "EffShift Strategy: Extrapolation of power consumption for current gear! n: {0}, Tq: {1}", - engineSpeed, tqCurrent); - } - return fcCurRes.ElectricalPower.Value(); - } - - - - - protected ResponseDryRun RequestDryRunWithGear( - Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, GearshiftPosition tryNextGear) - { - LogEnabled = false; - TestContainerGbx.Disengaged = false; - TestContainerGbx.Gear = tryNextGear; - - TestContainer.GearboxOutPort.Initialize(outTorque, outAngularVelocity); - var response = (ResponseDryRun)TestContainer.GearboxOutPort.Request( - 0.SI<Second>(), dt, outTorque, outAngularVelocity, true); - LogEnabled = true; - return response; - } - - protected MeterPerSquareSecond EstimateAccelerationForGear(GearshiftPosition gear, PerSecond gbxAngularVelocityOut) - { - if (!gear.Engaged || !GearList.Contains(gear)) { - throw new VectoSimulationException("EstimateAccelerationForGear: invalid gear: {0}", gear); - } - - var vehicleSpeed = DataBus.VehicleInfo.VehicleSpeed; - - var nextEngineSpeed = gbxAngularVelocityOut * GearboxModelData.Gears[gear.Gear].Ratio; - var maxEnginePower = -(VoltageLevels.FullLoadDriveTorque(DataBus.BatteryInfo.InternalVoltage, nextEngineSpeed) * nextEngineSpeed); - - var avgSlope = - ((DataBus.DrivingCycleInfo.CycleLookAhead(Constants.SimulationSettings.GearboxLookaheadForAccelerationEstimation).Altitude - - DataBus.DrivingCycleInfo.Altitude) / Constants.SimulationSettings.GearboxLookaheadForAccelerationEstimation).Value().SI<Radian>(); - - var airDragLoss = DataBus.VehicleInfo.AirDragResistance(vehicleSpeed, vehicleSpeed) * DataBus.VehicleInfo.VehicleSpeed; - var rollResistanceLoss = DataBus.VehicleInfo.RollingResistance(avgSlope) * DataBus.VehicleInfo.VehicleSpeed; - var gearboxLoss = GearboxModelData.Gears[gear.Gear].LossMap.GetTorqueLoss(gbxAngularVelocityOut, - maxEnginePower / nextEngineSpeed * GearboxModelData.Gears[gear.Gear].Ratio).Value * nextEngineSpeed; - //DataBus.GearboxLoss(); - var slopeLoss = DataBus.VehicleInfo.SlopeResistance(avgSlope) * DataBus.VehicleInfo.VehicleSpeed; - var axleLoss = DataBus.AxlegearInfo.AxlegearLoss(); - - var accelerationPower = maxEnginePower - gearboxLoss - axleLoss - airDragLoss - rollResistanceLoss - slopeLoss; - - var acceleration = accelerationPower / DataBus.VehicleInfo.VehicleSpeed / (DataBus.VehicleInfo.TotalMass + DataBus.WheelsInfo.ReducedMassWheels); - - return acceleration.Cast<MeterPerSquareSecond>(); - } - - protected virtual GearshiftPosition CheckDownshift(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, NewtonMeter inTorque, PerSecond inAngularVelocity, GearshiftPosition currentGear, IResponse response) - { - if ((absTime - _gearbox.LastUpshift).IsSmaller(GearshiftParams.DownshiftAfterUpshiftDelay)) { - SetShiftDecision(GearshiftTrigger.GearshiftBlockedTimeDelay, absTime); - return currentGear; - } - return DoCheckDownshift(absTime, dt, outTorque, outAngularVelocity, inTorque, inAngularVelocity, currentGear, response); - } - - protected virtual GearshiftPosition DoCheckDownshift( - Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, - NewtonMeter inTorque, PerSecond inAngularVelocity, GearshiftPosition currentGear, IResponse response) - { - var nextGear = BaseDoCheckDownshift( - absTime, dt, outTorque, outAngularVelocity, inTorque, inAngularVelocity, currentGear, response); - - if (nextGear.Equals(currentGear) && !currentGear.Equals(GearList.First())) { - nextGear = CheckEarlyDownshift(absTime, dt, outTorque, outAngularVelocity, currentGear, response); - if (nextGear != currentGear) { - SetShiftDecision(GearshiftTrigger.EfficiencyShift, absTime); - } - } - return nextGear; - } - - protected virtual GearshiftPosition BaseDoCheckDownshift(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, - NewtonMeter inTorque, PerSecond inAngularVelocity, GearshiftPosition currentGear, IResponse response) - { - // down shift - if (response.ElectricMotor.TorqueRequestEmMap == null) { - // em is off - no need to shift - return currentGear; - } - if (IsBelowDownShiftCurve(currentGear, response.ElectricMotor.TorqueRequestEmMap, response.ElectricMotor.AngularVelocity)) { - currentGear = GearList.Predecessor(currentGear); - SetShiftDecision(GearshiftTrigger.BelowDownshiftLine, absTime); - //while (SkipGears && currentGear > 1) { - // currentGear--; - // var response = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, currentGear); - - // inAngularVelocity = ModelData.Gears[currentGear].Ratio * outAngularVelocity; - // inTorque = response.ClutchPowerRequest / inAngularVelocity; - // var maxTorque = VectoMath.Min(response.DynamicFullLoadPower / ((DataBus.EngineSpeed + response.EngineSpeed) / 2), - // currentGear > 1 - // ? ModelData.Gears[currentGear].ShiftPolygon.InterpolateDownshift(response.EngineSpeed) - // : double.MaxValue.SI<NewtonMeter>()); - // var reserve = maxTorque.IsEqual(0) ? -1 : (1 - inTorque / maxTorque).Value(); - // if (reserve >= ModelData.TorqueReserve && IsBelowUpShiftCurve(currentGear, inTorque, inAngularVelocity)) { - // continue; - // } - // currentGear++; - // break; - //} - } - return currentGear; - } - - - protected virtual GearshiftPosition CheckEarlyDownshift(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, GearshiftPosition currentGear, IResponse response1) - { - //var minFcGear = currentGear; - //var minFc = double.MaxValue * Math.Sign(outTorque.Value()) ; - //var fcCurrent = double.NaN; - - var estimatedVelocityPostShift = VelocityDropData.Interpolate(DataBus.VehicleInfo.VehicleSpeed, DataBus.DrivingCycleInfo.RoadGradient ?? 0.SI<Radian>()); - if (!estimatedVelocityPostShift.IsGreater(DeclarationData.GearboxTCU.MIN_SPEED_AFTER_TRACTION_INTERRUPTION)) { - return currentGear; - } - - // no eff-shift if torque demand is close to ICE drag load - //if (response1.Engine.TorqueOutDemand.IsSmaller(DeclarationData.GearboxTCU.DragMarginFactor * fld[currentGear].DragLoadStationaryTorque(response1.Engine.EngineSpeed))) { - // 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; - - if (IsAboveUpShiftCurve(tryNextGear, inTorque, inAngularVelocity)) { - continue; - } - - var fcNext = GetFCRating(response); - results.Add(Tuple.Create(tryNextGear,fcNext)); - - } - - if (results.Count == 0) { - return currentGear; - } - - var responseCurrent = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, currentGear); - var fcCurrent = GetFCRating(responseCurrent); - - var minFc = results.MinBy(x => x.Item2); - - var ratingFactor = outTorque < 0 - ? 1 / shiftStrategyParameters.RatingFactorCurrentGear - : shiftStrategyParameters.RatingFactorCurrentGear; - - - if (minFc.Item2.IsGreater(fcCurrent * ratingFactor)) { - return minFc.Item1; - } - - return currentGear; - } - - - public GearshiftPosition InitGear(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity) - { - if (DataBus.VehicleInfo.VehicleSpeed.IsEqual(0)) { - return InitStartGear(absTime, outTorque, outAngularVelocity); - } - - foreach (var gear in GearList.Reverse()) { - //for (var gear = (uint)GearboxModelData.Gears.Count; gear > 1; gear--) { - var response = _gearbox.Initialize(absTime, gear, outTorque, outAngularVelocity); - - var inAngularSpeed = outAngularVelocity * GearboxModelData.Gears[gear.Gear].Ratio; - var inTorque = response.ElectricMotor.PowerRequest / inAngularSpeed; - - // if in shift curve and torque reserve is provided: return the current gear - if (!IsBelowDownShiftCurve(gear, inTorque, inAngularSpeed) && !IsAboveUpShiftCurve(gear, inTorque, inAngularSpeed)) { - _nextGear = gear; - return gear; - } - } - // fallback: return first gear - _nextGear = GearList.First(); - return _nextGear; - } - - private GearshiftPosition InitStartGear(Second absTime, NewtonMeter outTorque, PerSecond outAngularVelocity) - { - DriveOffStandstill = true; - - var emSpeeds = new Dictionary<GearshiftPosition, Tuple<PerSecond, PerSecond, double>>(); - - foreach (var gear in GearList.Reverse()) { - //for (var gear = (uint)GearboxModelData.Gears.Count; gear >= 1; gear--) { - var inAngularSpeed = outAngularVelocity * GearboxModelData.Gears[gear.Gear].Ratio; - - var ratedSpeed = VoltageLevels.MaxSpeed * 0.9; - if (inAngularSpeed > ratedSpeed || inAngularSpeed.IsEqual(0)) { - continue; - } - - var response = _gearbox.Initialize(absTime, gear, outTorque, outAngularVelocity); - - var fullLoadPower = -(response.ElectricMotor.MaxDriveTorque * response.ElectricMotor.AngularVelocity); - //.DynamicFullLoadPower; //EnginePowerRequest - response.DeltaFullLoad; - var reserve = 1 - response.ElectricMotor.TorqueRequestEmMap / response.ElectricMotor.MaxDriveTorqueEM; - - var isBelowDownshift = gear.Gear > 1 && - IsBelowDownshiftCurve(GearboxModelData.Gears[gear.Gear].ShiftPolygon, response.ElectricMotor.TorqueRequest, - response.ElectricMotor.AngularVelocity); - - if (reserve >= GearshiftParams.StartTorqueReserve && !isBelowDownshift) { - //_nextGear = gear; - //return gear; - emSpeeds[gear] = Tuple.Create(response.ElectricMotor.AngularVelocity, - (GearshiftParams.StartSpeed * TransmissionRatio * GearboxModelData.Gears[gear.Gear].Ratio) - .Cast<PerSecond>(), (response.ElectricMotor.ElectricMotorPowerMech / response.ElectricSystem.RESSPowerDemand).Value()); - } - } - - if (emSpeeds.Any()) { - var optimum = emSpeeds.MaxBy(x => x.Key.Gear); //x => VectoMath.Abs(x.Value.Item2 - FullLoadCurve.MaxSpeed * 0.5)); - _nextGear = optimum.Key; - return _nextGear; - } - _nextGear = GearList.First(); - return _nextGear; - } - - private bool IsBelowDownshiftCurve(ShiftPolygon shiftPolygon, NewtonMeter emTorque, PerSecond emSpeed) - { - foreach (var entry in shiftPolygon.Downshift.Pairwise(Tuple.Create)) { - if (!emTorque.IsBetween(entry.Item1.Torque, entry.Item2.Torque)) { - continue; - } - - if (ShiftPolygon.IsLeftOf(emSpeed, emTorque, entry)) { - - return true; - } - } - - return false; - } - - protected bool IsBelowDownShiftCurve(GearshiftPosition gear, NewtonMeter inTorque, PerSecond inEngineSpeed) - { - if (!GearList.HasPredecessor(gear)) { - return false; - } - return IsBelowDownshiftCurve(GearboxModelData.Gears[gear.Gear].ShiftPolygon, inTorque, inEngineSpeed); - } - - protected bool IsAboveDownShiftCurve(GearshiftPosition gear, NewtonMeter inTorque, PerSecond inEngineSpeed) - { - if (!GearList.HasPredecessor(gear)) { - return true; - } - return GearboxModelData.Gears[gear.Gear].ShiftPolygon.IsAboveDownshiftCurve(inTorque, inEngineSpeed); - } - - protected bool IsAboveUpShiftCurve(GearshiftPosition gear, NewtonMeter inTorque, PerSecond inEngineSpeed) - { - if (!GearList.HasSuccessor(gear)) { - return false; - } - return GearboxModelData.Gears[gear.Gear].ShiftPolygon.IsAboveUpshiftCurve(inTorque, inEngineSpeed); - } - - public GearshiftPosition Engage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity) - { - - while (GearList.HasSuccessor(_nextGear) && SpeedTooHighForEngine(_nextGear, outAngularVelocity)) { - _nextGear = GearList.Successor(_nextGear); - } - - return _nextGear; - } - - - protected bool SpeedTooHighForEngine(GearshiftPosition gear, PerSecond outAngularSpeed) - { - return - (outAngularSpeed * GearboxModelData.Gears[gear.Gear].Ratio).IsGreaterOrEqual(VectoMath.Min(GearboxModelData.Gears[gear.Gear].MaxSpeed, - DataBus.ElectricMotorInfo(PowertrainPosition.BatteryElectricE2).MaxSpeed)); - } - - public void Disengage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity) { } - - public IGearbox Gearbox { - get => _gearbox; - set { - var myGearbox = value as Gearbox; - if (myGearbox == null) { - throw new VectoException("This shift strategy can't handle gearbox of type {0}", value.GetType()); - } - _gearbox = myGearbox; - } - } - - public GearshiftPosition NextGear => _nextGear; - - - public bool CheckGearshiftRequired { get; protected set; } - public GearshiftPosition MaxStartGear { get; } - - public void Request(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity) - { - if (!absTime.IsEqual(ShiftDecisionTstmp)) { - ShiftTrigger = GearshiftTrigger.NoShift; - } - - ShiftDecisionTstmp = absTime; - } - - protected void SetShiftDecision(GearshiftTrigger trigger, Second absTime) - { - ShiftTrigger = trigger; - } - - public void WriteModalResults(IModalDataContainer container) { } - - public ShiftPolygon ComputeDeclarationShiftPolygon(GearboxType gearboxType, int i, EngineFullLoadCurve engineDataFullLoadCurve, - IList<ITransmissionInputData> gearboxGears, CombustionEngineData engineData, double axlegearRatio, Meter dynamicTyreRadius, ElectricMotorData electricMotorData) - { - return DeclarationData.Gearbox.ComputeElectricMotorShiftPolygon(i, electricMotorData.EfficiencyData.VoltageLevels.First().FullLoadCurve, electricMotorData.RatioADC, gearboxGears, axlegearRatio, dynamicTyreRadius); - } - - } } \ No newline at end of file diff --git a/VectoCore/VectoCoreTest/Integration/BatteryElectric/BatteryElectricTest.cs b/VectoCore/VectoCoreTest/Integration/BatteryElectric/BatteryElectricTest.cs index 7b5662db24..e537c19dbb 100644 --- a/VectoCore/VectoCoreTest/Integration/BatteryElectric/BatteryElectricTest.cs +++ b/VectoCore/VectoCoreTest/Integration/BatteryElectric/BatteryElectricTest.cs @@ -22,6 +22,7 @@ using TUGraz.VectoCore.Models.SimulationComponent.Impl; using TUGraz.VectoCore.Models.SimulationComponent.Strategies; using TUGraz.VectoCore.OutputData; using TUGraz.VectoCore.OutputData.FileIO; +using TUGraz.VectoCore.Tests.Models.SimulationComponentData; using TUGraz.VectoCore.Tests.Utils; using TUGraz.VectoCore.Utils; using ElectricSystem = TUGraz.VectoCore.Models.SimulationComponent.ElectricSystem; @@ -42,6 +43,7 @@ namespace TUGraz.VectoCore.Tests.Integration.BatteryElectric protected const string BEV_E2_Job = @"TestData\BatteryElectric\GenericVehicleB2\BEV_ENG.vecto"; + protected const string BEV_E2_Job_3Speed = @"TestData\BatteryElectric\GenericVehicleB2\BEV_ENG_3speed.vecto"; protected const string BEV_E2_Job_Cont30kW = @"TestData\BatteryElectric\GenericVehicleB2\BEV_ENG_Cont30kW.vecto"; public const string MotorFile = @"TestData\BatteryElectric\GenericVehicleB4\GenericEMotor_125kW_485Nm.vem"; @@ -565,6 +567,17 @@ namespace TUGraz.VectoCore.Tests.Integration.BatteryElectric TestCase(BEV_E2_Job, 8, TestName = "PEV E2 Job Urban"), TestCase(BEV_E2_Job, 9, TestName = "PEV E2 Job UrbanDelivery"), + TestCase(BEV_E2_Job_3Speed, 0, TestName = "PEV E2 3Speed Job LongHaul"), + TestCase(BEV_E2_Job_3Speed, 1, TestName = "PEV E2 3Speed Job Coach"), + TestCase(BEV_E2_Job_3Speed, 2, TestName = "PEV E2 3Speed Job Construction"), + TestCase(BEV_E2_Job_3Speed, 3, TestName = "PEV E2 3Speed Job HeavyUrban"), + TestCase(BEV_E2_Job_3Speed, 4, TestName = "PEV E2 3Speed Job Interurban"), + TestCase(BEV_E2_Job_3Speed, 5, TestName = "PEV E2 3Speed Job MunicipalUtility"), + TestCase(BEV_E2_Job_3Speed, 6, TestName = "PEV E2 3Speed Job RegionalDelivery"), + TestCase(BEV_E2_Job_3Speed, 7, TestName = "PEV E2 3Speed Job Suburban"), + TestCase(BEV_E2_Job_3Speed, 8, TestName = "PEV E2 3Speed Job Urban"), + TestCase(BEV_E2_Job_3Speed, 9, TestName = "PEV E2 3Speed Job UrbanDelivery"), + TestCase(BEV_E2_Job_Cont30kW, 0, TestName = "PEV E2 Cont. 30kW Job LongHaul"), TestCase(BEV_E2_Job_Cont30kW, 1, TestName = "PEV E2 Cont. 30kW Job Coach"), TestCase(BEV_E2_Job_Cont30kW, 2, TestName = "PEV E2 Cont. 30kW Job Construction"), @@ -788,7 +801,12 @@ namespace TUGraz.VectoCore.Tests.Integration.BatteryElectric Inertia = 0.SI<KilogramSquareMeter>(), TractionInterruption = 1.SI<Second>(), - + InputData = new DummyGearboxData() { + Gears = new List<ITransmissionInputData>() { + new TransmissionInputData(), + new TransmissionInputData(), + } + } }; } diff --git a/VectoCore/VectoCoreTest/Models/Declaration/ShiftPolygonTest.cs b/VectoCore/VectoCoreTest/Models/Declaration/ShiftPolygonTest.cs index 1d22ae3e10..fe3bcbe008 100644 --- a/VectoCore/VectoCoreTest/Models/Declaration/ShiftPolygonTest.cs +++ b/VectoCore/VectoCoreTest/Models/Declaration/ShiftPolygonTest.cs @@ -43,9 +43,13 @@ using TUGraz.VectoCore.InputData.FileIO.XML; using TUGraz.VectoCore.InputData.Reader.ComponentData; using TUGraz.VectoCore.InputData.Reader.DataObjectAdapter; using TUGraz.VectoCore.Models.Declaration; +using TUGraz.VectoCore.Models.Simulation.Data; +using TUGraz.VectoCore.Models.Simulation.Impl; using TUGraz.VectoCore.Models.SimulationComponent.Data; +using TUGraz.VectoCore.Models.SimulationComponent.Data.ElectricMotor; using TUGraz.VectoCore.Models.SimulationComponent.Data.Engine; using TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox; +using TUGraz.VectoCore.Models.SimulationComponent.Impl; using TUGraz.VectoCore.Tests.Utils; using TUGraz.VectoCore.Utils; using Point = TUGraz.VectoCommon.Utils.Point; @@ -922,11 +926,10 @@ namespace TUGraz.VectoCore.Tests.Models.Declaration } } - [TestCase()] - public void ComputePEVShiftLines() + [TestCase(@"TestData\BatteryElectric\GenericVehicleB2\BEV_ENG.vecto"), + TestCase(@"TestData\BatteryElectric\GenericVehicleB2\BEV_ENG_cont30kW.vecto")] + public void ComputePEVShiftLines(string pevE2Job) { - var pevE2Job = @"TestData\BatteryElectric\GenericVehicleB2\BEV_ENG.vecto"; - var inputData = JSONInputDataFactory.ReadJsonJob(pevE2Job) as IEngineeringInputDataProvider; var gearboxData = inputData.JobInputData.Vehicle.Components.GearboxInputData; var dao = new EngineeringDataAdapter(); @@ -959,5 +962,67 @@ namespace TUGraz.VectoCore.Tests.Models.Declaration imageFile, DeclarationData.Gearbox.TruckMaxAllowedSpeed / r_dyn * axlegearRatio * gearboxData.Gears.Last().Ratio); } + + [TestCase()] + public void ComputePEVShiftLinesDeRated() + { + var pevE2Job = @"TestData\BatteryElectric\GenericVehicleB2\BEV_ENG_cont30kW.vecto"; + + var inputData = JSONInputDataFactory.ReadJsonJob(pevE2Job) as IEngineeringInputDataProvider; + var gearboxData = inputData.JobInputData.Vehicle.Components.GearboxInputData; + var dao = new EngineeringDataAdapter(); + var emData = dao.CreateElectricMachines(inputData.JobInputData.Vehicle.Components.ElectricMachines, + null).FirstOrDefault()?.Item2; + + var axlegearRatio = inputData.JobInputData.Vehicle.Components.AxleGearInputData.Ratio; + var vehicleData = dao.CreateVehicleData(inputData.JobInputData.Vehicle); + var r_dyn = vehicleData.DynamicTyreRadius; + + //emData.ContinuousTorque = 500.SI<NewtonMeter>(); + var contTqFld = new ElectricMotorFullLoadCurve(new List<ElectricMotorFullLoadCurve.FullLoadEntry>() { + new ElectricMotorFullLoadCurve.FullLoadEntry() { + MotorSpeed = 0.RPMtoRad(), + FullDriveTorque = -emData.ContinuousTorque, + FullGenerationTorque = emData.ContinuousTorque + }, + new ElectricMotorFullLoadCurve.FullLoadEntry() { + MotorSpeed = 1.1 * emData.EfficiencyData.VoltageLevels.First().FullLoadCurve.MaxSpeed, + FullDriveTorque = -emData.ContinuousTorque, + FullGenerationTorque = emData.ContinuousTorque + } + }); + var limitedFld = AbstractSimulationDataAdapter.IntersectEMFullLoadCurves(emData.EfficiencyData.VoltageLevels.First().FullLoadCurve, contTqFld); + + var fullLoadCurve = limitedFld.FullLoadEntries.Select(x => + new EngineFullLoadCurve.FullLoadCurveEntry() { + EngineSpeed = x.MotorSpeed, + TorqueFullLoad = -x.FullDriveTorque, + TorqueDrag = -x.FullGenerationTorque + }).ToList(); + var fullLoadCurves = new Dictionary<uint, EngineFullLoadCurve>(); + var engineData = new CombustionEngineData() { + IdleSpeed = 600.RPMtoRad() + }; + fullLoadCurves[(uint)(0)] = new EngineFullLoadCurve(fullLoadCurve, null) { EngineData = engineData }; + + + var shiftPolygons = new List<ShiftPolygon>(); + + var shiftStrategy = new PEVAMTShiftStrategy(new VehicleContainer(ExecutionMode.Engineering) { RunData = new VectoRunData() { GearshiftParameters = new ShiftStrategyParameters()}}); + var deRatedShiftLines = shiftStrategy.CalculateDeratedShiftLines(emData, gearboxData.Gears, + r_dyn, axlegearRatio, gearboxData.Type); + for (var i = 0; i < gearboxData.Gears.Count; i++) { + + shiftPolygons.Add(deRatedShiftLines[(uint)(i + 1)]); + + + fullLoadCurves[(uint)(i + 1)] = new EngineFullLoadCurve(fullLoadCurve, null) { EngineData = engineData }; + } + var imageFile = Path.Combine(Path.GetDirectoryName(pevE2Job), Path.GetFileNameWithoutExtension(pevE2Job) + "_shiftlines_DeRated.png"); + + ShiftPolygonDrawer.DrawShiftPolygons(Path.GetDirectoryName(pevE2Job), fullLoadCurves, shiftPolygons, + imageFile, + DeclarationData.Gearbox.TruckMaxAllowedSpeed / r_dyn * axlegearRatio * gearboxData.Gears.Last().Ratio); + } } } \ No newline at end of file diff --git a/VectoCore/VectoCoreTest/TestData/BatteryElectric/GenericVehicleB2/3speedEV.vgbx b/VectoCore/VectoCoreTest/TestData/BatteryElectric/GenericVehicleB2/3speedEV.vgbx new file mode 100644 index 0000000000..2899660e38 --- /dev/null +++ b/VectoCore/VectoCoreTest/TestData/BatteryElectric/GenericVehicleB2/3speedEV.vgbx @@ -0,0 +1,54 @@ +{ + "Header": { + "CreatedBy": "", + "Date": "2020-11-03T14:19:09.9858299Z", + "AppVersion": "3", + "FileVersion": 6 + }, + "Body": { + "SavedInDeclMode": false, + "ModelName": "3_speed_AMT", + "Inertia": 0.0, + "TracInt": 0.8, + "Gears": [ + { + "Ratio": 2.64, + "LossMap": "Transmission\\Axle_4x2_Tractor.vtlm" + }, + { + "Ratio": 17.5, + "LossMap": "Transmission\\Gear_1.vtlm", + "ShiftPolygon": "", + "MaxTorque": "", + "MaxSpeed": "" + }, + { + "Ratio": 6.49, + "LossMap": "Transmission\\Gear_2.vtlm", + "ShiftPolygon": "", + "MaxTorque": "", + "MaxSpeed": "" + }, + { + "Ratio": 2.48, + "LossMap": "Transmission\\Gear_3.vtlm", + "ShiftPolygon": "", + "MaxTorque": "", + "MaxSpeed": "" + } + ], + "TqReserve": 0.0, + "ShiftTime": 2.0, + "StartTqReserve": 20.0, + "StartSpeed": 2.22222222222222, + "StartAcc": 0.8, + "GearboxType": "AMT", + "TorqueConverter": { + "Enabled": false + }, + "DownshiftAfterUpshiftDelay": 6.0, + "UpshiftAfterDownshiftDelay": 6.0, + "UpshiftMinAcceleration": 0.1, + "PowershiftShiftTime": 0.0 + } +} \ No newline at end of file diff --git a/VectoCore/VectoCoreTest/TestData/BatteryElectric/GenericVehicleB2/BEV_ENG_3speed.vecto b/VectoCore/VectoCoreTest/TestData/BatteryElectric/GenericVehicleB2/BEV_ENG_3speed.vecto new file mode 100644 index 0000000000..ec266b20cc --- /dev/null +++ b/VectoCore/VectoCoreTest/TestData/BatteryElectric/GenericVehicleB2/BEV_ENG_3speed.vecto @@ -0,0 +1,45 @@ +{ + "Header": { + "CreatedBy": " ()", + "Date": "2016-10-13T08:55:18.2100810Z", + "AppVersion": "3", + "FileVersion": 9 + }, + "Body": { + "SavedInDeclMode": false, + "EngineOnlyMode": false, + "VehicleFile": "BatteryElectricVehicle.vveh", + "GearboxFile": "3speedEV.vgbx", + "TCU": "3speedEV.vgbx", + "Padd_electric": 3540.0, + + "VACC": "Truck.vacc", + + "LAC": { + "Enabled": true, + "PreviewDistanceFactor": 10.0, + "DF_offset": 2.5, + "DF_scaling": 1.5, + "DF_targetSpeedLookup": "", + "Df_velocityDropLookup": "" + }, + "OverSpeedEcoRoll": { + "Mode": "Off", + "MinSpeed": 50.0, + "OverSpeed": 5.0, + "UnderSpeed": 5.0 + }, + "Cycles": [ + "LongHaul", + "Coach", + "Construction", + "HeavyUrban", + "Interurban", + "MunicipalUtility", + "RegionalDelivery", + "Suburban", + "Urban", + "UrbanDelivery" + ] + } +} \ No newline at end of file diff --git a/VectoCore/VectoCoreTest/VectoCoreTest.csproj b/VectoCore/VectoCoreTest/VectoCoreTest.csproj index c60edb48e0..c48ad12d6f 100644 --- a/VectoCore/VectoCoreTest/VectoCoreTest.csproj +++ b/VectoCore/VectoCoreTest/VectoCoreTest.csproj @@ -250,6 +250,9 @@ <SubType>Designer</SubType> </None> <None Include="default.runsettings" /> + <None Include="TestData\BatteryElectric\GenericVehicleB2\3speedEV.vgbx"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> <None Include="TestData\BatteryElectric\GenericVehicleB2\BatteryElectricVehicle.vveh"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> @@ -259,6 +262,9 @@ <None Include="TestData\BatteryElectric\GenericVehicleB2\BEV_ENG.vecto"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> + <None Include="TestData\BatteryElectric\GenericVehicleB2\BEV_ENG_3speed.vecto"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </None> <None Include="TestData\BatteryElectric\GenericVehicleB2\BEV_ENG_Cont30kW.vecto"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> -- GitLab