From baf362832c5ff85106c1fa468fd8c7eab3b80715 Mon Sep 17 00:00:00 2001 From: Markus Quaritsch <Markus.Quaritsch@tugraz.at> Date: Thu, 26 Mar 2020 11:15:11 +0100 Subject: [PATCH] hybrid controller works on simple cycle with gearshifting --- .../VectoCommon/Models/PowertrainPosition.cs | 5 ++ .../Simulation/Data/ModalResultField.cs | 26 +++---- .../IHybridControlStrategy.cs | 1 + .../Impl/HybridController.cs | 7 +- .../DelegateParallelHybridStrategy.cs | 7 ++ .../Strategies/HybridStrategy.cs | 5 ++ .../OutputData/ModalDataContainer.cs | 75 ++++++++++++------- .../Integration/Hybrid/ParallelHybridTest.cs | 42 +++++++++-- 8 files changed, 121 insertions(+), 47 deletions(-) diff --git a/VectoCommon/VectoCommon/Models/PowertrainPosition.cs b/VectoCommon/VectoCommon/Models/PowertrainPosition.cs index de65b8ae9c..1d5f6fb91a 100644 --- a/VectoCommon/VectoCommon/Models/PowertrainPosition.cs +++ b/VectoCommon/VectoCommon/Models/PowertrainPosition.cs @@ -18,5 +18,10 @@ namespace TUGraz.VectoCommon.InputData { { return (Prefix + pos).ParseEnum<PowertrainPosition>(); } + + public static string GetName(this PowertrainPosition pos) + { + return pos.ToString().Replace(Prefix, ""); + } } } \ No newline at end of file diff --git a/VectoCore/VectoCore/Models/Simulation/Data/ModalResultField.cs b/VectoCore/VectoCore/Models/Simulation/Data/ModalResultField.cs index 10a6ce6264..ec8244206d 100644 --- a/VectoCore/VectoCore/Models/Simulation/Data/ModalResultField.cs +++ b/VectoCore/VectoCore/Models/Simulation/Data/ModalResultField.cs @@ -374,19 +374,19 @@ namespace TUGraz.VectoCore.Models.Simulation.Data [ModalResultField(typeof(SI), "P_WHR_mech [kW]", outputFactor: 1e-3)] P_WHR_mech_map, [ModalResultField(typeof(SI), "P_WHR_mech_corr [kW]", outputFactor: 1e-3)] P_WHR_mech_corr, - [ModalResultField(typeof(SI), caption: "n_em{0}_avg [1/min]", outputFactor: 60 / (2 * Math.PI))] n_electricMotor_, - [ModalResultField(typeof(SI), caption: "T_em{0} [Nm]")] T_electricMotor_, - [ModalResultField(typeof(SI), caption: "T_em{0}_full [Nm]")] T_electricMotor_full_, - [ModalResultField(typeof(SI), caption: "T_em{0}_drag [Nm]")] T_electricMotor_drag_, - [ModalResultField(typeof(SI), caption: "P_em{0}_in [kW]", outputFactor: 1e-3)] P_electricMotor_in_, - [ModalResultField(typeof(SI), caption: "P_em{0}_out [kW]", outputFactor: 1e-3)] P_electricMotor_out_, - [ModalResultField(typeof(SI), caption: "P_em{0}_mech [kW]", outputFactor: 1e-3)] P_electricMotor_mech_, - [ModalResultField(typeof(SI), caption: "P_em{0}_el [kW]", outputFactor: 1e-3)] P_electricMotor_el_, - [ModalResultField(typeof(SI), caption: "P_em{0}_drag_max_ [kW]", outputFactor: 1e-3)] P_electricMotor_drag_max_, - [ModalResultField(typeof(SI), caption: "P_em{0}_drive_max [kW]", outputFactor: 1e-3)] P_electricMotor_drive_max_, - [ModalResultField(typeof(SI), caption: "P_em{0}_brake [kW]", outputFactor: 1e-3)] P_electricMotor_brake_, - [ModalResultField(typeof(SI), caption: "P_em{0}_loss [kW]", outputFactor: 1e-3)] P_electricMotorLoss_, - [ModalResultField(typeof(SI), caption: "P_em{0}_inertia_loss [kW]", outputFactor: 1e-3)] P_electricMotorInertiaLoss_, + [ModalResultField(typeof(SI), caption: "n_em-{0}_avg [1/min]", outputFactor: 60 / (2 * Math.PI))] n_electricMotor_, + [ModalResultField(typeof(SI), caption: "T_em-{0} [Nm]")] T_electricMotor_, + [ModalResultField(typeof(SI), caption: "T_em-{0}_full [Nm]")] T_electricMotor_full_, + [ModalResultField(typeof(SI), caption: "T_em-{0}_drag [Nm]")] T_electricMotor_drag_, + [ModalResultField(typeof(SI), caption: "P_em-{0}_in [kW]", outputFactor: 1e-3)] P_electricMotor_in_, + [ModalResultField(typeof(SI), caption: "P_em-{0}_out [kW]", outputFactor: 1e-3)] P_electricMotor_out_, + [ModalResultField(typeof(SI), caption: "P_em-{0}_mech [kW]", outputFactor: 1e-3)] P_electricMotor_mech_, + [ModalResultField(typeof(SI), caption: "P_em-{0}_el [kW]", outputFactor: 1e-3)] P_electricMotor_el_, + [ModalResultField(typeof(SI), caption: "P_em-{0}_drag_max_ [kW]", outputFactor: 1e-3)] P_electricMotor_drag_max_, + [ModalResultField(typeof(SI), caption: "P_em-{0}_drive_max [kW]", outputFactor: 1e-3)] P_electricMotor_drive_max_, + [ModalResultField(typeof(SI), caption: "P_em-{0}_brake [kW]", outputFactor: 1e-3)] P_electricMotor_brake_, + [ModalResultField(typeof(SI), caption: "P_em-{0}_loss [kW]", outputFactor: 1e-3)] P_electricMotorLoss_, + [ModalResultField(typeof(SI), caption: "P_em-{0}_inertia_loss [kW]", outputFactor: 1e-3)] P_electricMotorInertiaLoss_, [ModalResultField(typeof(SI), caption: "P_bat_T [kW]", outputFactor: 1e-3)] P_battery_terminal, [ModalResultField(typeof(SI), caption: "P_bat_int [kW]", outputFactor: 1e-3)] P_battery_int, diff --git a/VectoCore/VectoCore/Models/SimulationComponent/IHybridControlStrategy.cs b/VectoCore/VectoCore/Models/SimulationComponent/IHybridControlStrategy.cs index 9955b9e13c..8193d17a1e 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/IHybridControlStrategy.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/IHybridControlStrategy.cs @@ -16,5 +16,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent { HybridStrategyResponse Request(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, bool dryRun); HybridStrategyResponse Initialize(NewtonMeter outTorque, PerSecond outAngularVelocity); + void CommitSimulationStep(); } } \ No newline at end of file diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/HybridController.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/HybridController.cs index 84c166dbcf..091c127416 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/HybridController.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/HybridController.cs @@ -63,7 +63,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl bool dryRun = false) { CurrentState.StrategyResponse = Strategy.Request(absTime, dt, outTorque, outAngularVelocity, dryRun); - return NextComponent.Request(absTime, dt, outTorque, outAngularVelocity); + return NextComponent.Request(absTime, dt, outTorque, outAngularVelocity, dryRun); } public IResponse Initialize(NewtonMeter outTorque, PerSecond outAngularVelocity) @@ -72,6 +72,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return NextComponent.Initialize(outTorque, outAngularVelocity); } + protected override void DoCommitSimulationStep() + { + base.DoCommitSimulationStep(); + Strategy.CommitSimulationStep(); + } protected override void DoWriteModalResults(Second time, Second simulationInterval, IModalDataContainer container) { } diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Strategies/DelegateParallelHybridStrategy.cs b/VectoCore/VectoCore/Models/SimulationComponent/Strategies/DelegateParallelHybridStrategy.cs index 1af43d6db2..b4cd9ff212 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Strategies/DelegateParallelHybridStrategy.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Strategies/DelegateParallelHybridStrategy.cs @@ -10,6 +10,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies public Func<NewtonMeter, PerSecond, HybridStrategyResponse> InitializeFunc { get; set; } public Func<Second, Second, NewtonMeter, PerSecond, bool, HybridStrategyResponse> RequestFunc { get; set; } + public Action CommitFunc { get; set; } + public HybridStrategyResponse Request(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, bool dryRun) { @@ -21,5 +23,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies { return InitializeFunc(outTorque, outAngularVelocity); } + + public void CommitSimulationStep() + { + CommitFunc(); + } } } \ No newline at end of file diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Strategies/HybridStrategy.cs b/VectoCore/VectoCore/Models/SimulationComponent/Strategies/HybridStrategy.cs index 6b3b76c7cc..40a2c1452c 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Strategies/HybridStrategy.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Strategies/HybridStrategy.cs @@ -25,6 +25,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies return new HybridStrategyResponse() { MechanicalAssistPower = new Dictionary<PowertrainPosition, NewtonMeter>() }; } + + public void CommitSimulationStep() + { + + } } diff --git a/VectoCore/VectoCore/OutputData/ModalDataContainer.cs b/VectoCore/VectoCore/OutputData/ModalDataContainer.cs index 1f3fb55d89..f4a75d388d 100644 --- a/VectoCore/VectoCore/OutputData/ModalDataContainer.cs +++ b/VectoCore/VectoCore/OutputData/ModalDataContainer.cs @@ -43,6 +43,7 @@ using TUGraz.VectoCommon.Utils; using TUGraz.VectoCore.Models.Declaration; using TUGraz.VectoCore.Models.Simulation.Data; using TUGraz.VectoCore.Models.Simulation.Impl; +using TUGraz.VectoCore.Models.SimulationComponent.Impl; namespace TUGraz.VectoCore.OutputData { @@ -62,6 +63,16 @@ namespace TUGraz.VectoCore.OutputData private Second _duration; private Meter _distance; + private readonly ModalResultField[] _electricMotorColumns = new[] { + ModalResultField.n_electricMotor_, ModalResultField.T_electricMotor_, + ModalResultField.T_electricMotor_full_, ModalResultField.T_electricMotor_drag_, + ModalResultField.P_electricMotor_in_, ModalResultField.P_electricMotor_out_, + ModalResultField.P_electricMotor_mech_, ModalResultField.P_electricMotor_el_, + ModalResultField.P_electricMotorLoss_, ModalResultField.P_electricMotorInertiaLoss_, + ModalResultField.P_electricMotor_brake_, ModalResultField.P_electricMotor_drive_max_, + ModalResultField.P_electricMotor_drag_max_ + }; + public static readonly IList<ModalResultField> FuelConsumptionSignals = new[] { ModalResultField.FCMap, ModalResultField.FCNCVc, ModalResultField.FCWHTCc, // ModalResultField.FCAAUX, ModalResultField.FCICEStopStart, ModalResultField.FCFinal @@ -69,6 +80,7 @@ namespace TUGraz.VectoCore.OutputData private readonly Dictionary<String, SI> _timeIntegrals = new Dictionary<string, SI>(); private readonly Dictionary<FuelType, KilogramPerWattSecond> _vehicleLine = new Dictionary<FuelType, KilogramPerWattSecond>(); + private List<PowertrainPosition> ElectricMotors = new List<PowertrainPosition>(); public int JobRunId { get; } public string RunName { get; } @@ -231,18 +243,9 @@ namespace TUGraz.VectoCore.OutputData public void AddElectricMotor(PowertrainPosition pos) { - var electricMotorColumns = new[] { - ModalResultField.n_electricMotor_, ModalResultField.T_electricMotor_, - ModalResultField.T_electricMotor_full_, ModalResultField.T_electricMotor_drag_, - ModalResultField.P_electricMotor_in_, ModalResultField.P_electricMotor_out_, - ModalResultField.P_electricMotor_mech_, ModalResultField.P_electricMotor_el_, - ModalResultField.P_electricMotorLoss_, ModalResultField.P_electricMotorInertiaLoss_, - ModalResultField.P_electricMotor_brake_, ModalResultField.P_electricMotor_drive_max_, - ModalResultField.P_electricMotor_drag_max_ - }; - foreach (var entry in electricMotorColumns) - { - var col = Data.Columns.Add(string.Format(entry.GetAttribute().Caption, pos.ToString()), typeof(SI)); + ElectricMotors.Add(pos); + foreach (var entry in _electricMotorColumns) { + var col = Data.Columns.Add(string.Format(entry.GetAttribute().Caption, pos.GetName()), typeof(SI)); col.ExtendedProperties[ModalResults.ExtendedPropertyNames.Decimals] = entry.GetAttribute().Decimals; col.ExtendedProperties[ModalResults.ExtendedPropertyNames.OutputFactor] = @@ -308,8 +311,7 @@ namespace TUGraz.VectoCore.OutputData var dataColumns = GetOutputColumns(); - var strCols = dataColumns.Select(x => x.GetName()) - .Concat(Auxiliaries.Values.Select(c => c.ColumnName)) + var strCols = dataColumns.Concat(Auxiliaries.Values.Select(c => c.ColumnName)) .Concat( new[] { ModalResultField.P_WHR_el_map, ModalResultField.P_WHR_el_corr, ModalResultField.P_WHR_mech_map, ModalResultField.P_WHR_mech_corr, ModalResultField.P_aux_ice_off, @@ -342,9 +344,9 @@ namespace TUGraz.VectoCore.OutputData _addReportResult(this); } - private IList<ModalResultField> GetOutputColumns() + private IList<string> GetOutputColumns() { - var dataColumns = new List<ModalResultField> { ModalResultField.time }; + var dataColumns = new List<string> { ModalResultField.time.GetName() }; if (!_writeEngineOnly) { dataColumns.AddRange( @@ -356,15 +358,15 @@ namespace TUGraz.VectoCore.OutputData ModalResultField.acc, ModalResultField.grad, ModalResultField.altitude - }); + }.Select(x => x.GetName())); } if (!_writeEngineOnly) { dataColumns.AddRange( new[] { ModalResultField.Gear, - }); + }.Select(x => x.GetName())); if (HasTorqueConverter) { - dataColumns.AddRange(new[] { ModalResultField.TC_Locked }); + dataColumns.AddRange(new[] { ModalResultField.TC_Locked }.Select(x => x.GetName())); } } dataColumns.AddRange( @@ -379,25 +381,42 @@ namespace TUGraz.VectoCore.OutputData ModalResultField.P_ice_drag, ModalResultField.P_ice_inertia, ModalResultField.P_ice_out, - }); + }.Select(x => x.GetName())); + if (ElectricMotors.Count > 0) { + dataColumns.AddRange(new[] { + ModalResultField.P_battery_terminal, + ModalResultField.P_battery_int, + ModalResultField.P_battery_loss, + ModalResultField.P_battery_charge_max, + ModalResultField.P_battery_discharge_max, + ModalResultField.BatteryStateOfCharge, + ModalResultField.U_bat_terminal, + ModalResultField.U0_bat, + ModalResultField.I_bat + }.Select(x => x.GetName())); + foreach (var em in ElectricMotors.OrderBy(x => x).Reverse()) { + dataColumns.AddRange(_electricMotorColumns.Select(emCol => + string.Format(emCol.GetAttribute().Caption, em.GetName()))); + } + } if (HasTorqueConverter) { dataColumns.AddRange( new[] { ModalResultField.P_gbx_shift_loss, ModalResultField.P_TC_loss, ModalResultField.P_TC_out, - }); + }.Select(x => x.GetName())); } else { dataColumns.AddRange( new[] { ModalResultField.P_clutch_loss, ModalResultField.P_clutch_out, - }); + }.Select(x => x.GetName())); } dataColumns.AddRange( new[] { ModalResultField.P_aux_mech - }); + }.Select(x => x.GetName())); if (!_writeEngineOnly) { dataColumns.AddRange( @@ -422,7 +441,7 @@ namespace TUGraz.VectoCore.OutputData ModalResultField.P_veh_inertia, ModalResultField.n_gbx_out_avg, ModalResultField.T_gbx_out - }); + }.Select(x => x.GetName())); if (WriteAdvancedAux) { dataColumns.AddRange( new[] { @@ -441,7 +460,7 @@ namespace TUGraz.VectoCore.OutputData ModalResultField.P_busAux_PS_generated, ModalResultField.P_busAux_PS_generated_alwaysOn, ModalResultField.P_busAux_PS_generated_dragOnly, - }); + }.Select(x => x.GetName())); } if (HasTorqueConverter) { dataColumns.AddRange( @@ -452,7 +471,7 @@ namespace TUGraz.VectoCore.OutputData ModalResultField.TC_angularSpeedOut, ModalResultField.TC_TorqueIn, ModalResultField.TC_angularSpeedIn, - }); + }.Select(x => x.GetName())); } } //if (!_writeEngineOnly && WriteAdvancedAux) { @@ -546,8 +565,8 @@ namespace TUGraz.VectoCore.OutputData public object this[ModalResultField key, PowertrainPosition pos] { - get { return CurrentRow[string.Format(key.GetCaption(), pos.ToString())]; } - set { CurrentRow[string.Format(key.GetCaption(), pos)] = value; } + get { return CurrentRow[string.Format(key.GetCaption(), pos.GetName())]; } + set { CurrentRow[string.Format(key.GetCaption(), pos.GetName())] = value; } } public object this[string auxId] diff --git a/VectoCore/VectoCoreTest/Integration/Hybrid/ParallelHybridTest.cs b/VectoCore/VectoCoreTest/Integration/Hybrid/ParallelHybridTest.cs index 5614fe85c3..7723974f97 100644 --- a/VectoCore/VectoCoreTest/Integration/Hybrid/ParallelHybridTest.cs +++ b/VectoCore/VectoCoreTest/Integration/Hybrid/ParallelHybridTest.cs @@ -52,7 +52,11 @@ namespace TUGraz.VectoCore.Tests.Integration.Hybrid @" 0, 0, 0, 3 700, {0}, 0, 0", vmax); var cycle = SimpleDrivingCycles.CreateCycleData(cycleData); + RunHybridSimulation(vmax, initialSoC, electricTorque, cycle); + } + public void RunHybridSimulation(double vmax, double initialSoC, double electricTorque, DrivingCycleData cycle) + { const bool largeMotor = true; var run = CreateEngineeringRun( cycle, string.Format("SimpleParallelHybrid_acc_{0}_{2}-{1}.vmod", vmax, initialSoC, electricTorque), initialSoC, @@ -65,16 +69,37 @@ namespace TUGraz.VectoCore.Tests.Integration.Hybrid var modData = ((ModalDataContainer)((VehicleContainer)run.GetContainer()).ModData).Data; - strategy.RequestFunc = (a, b, c, d, e) => new HybridStrategyResponse { - MechanicalAssistPower = new Dictionary<PowertrainPosition, NewtonMeter>() - { { PowertrainPosition.HybridP2, 0.SI<NewtonMeter>() } }, - ShiftRequired = run.GetContainer().EngineSpeed > 1600.RPMtoRad() || run.GetContainer().EngineSpeed < 680.RPMtoRad(), - NextGear = (uint)(run.GetContainer().Gear + (run.GetContainer().EngineSpeed > 1600.RPMtoRad() ? 1 : (run.GetContainer().EngineSpeed < 680.RPMtoRad() ? -1 : 0))) + var nextState = new StrategyState(); + var currentState = new StrategyState(); + strategy.RequestFunc = (absTime, b, c, d, dryRun) => { + var shiftAllowed = absTime > currentState.lastGearShift + 2.SI<Second>(); + var triggerGearshift = shiftAllowed && ( run.GetContainer().EngineSpeed > 1600.RPMtoRad() || + run.GetContainer().EngineSpeed < 625.RPMtoRad()); + //var nextGear = run.GetContainer().Gear; + if (!dryRun && triggerGearshift) { + nextState.lastGearShift = absTime; + nextState.nextGear = (uint)(run.GetContainer().Gear + (run.GetContainer().EngineSpeed > 1600.RPMtoRad() + ? 1 + : (run.GetContainer().EngineSpeed < 625.RPMtoRad() ? -1 : 0))); + } + return new HybridStrategyResponse { + MechanicalAssistPower = new Dictionary<PowertrainPosition, NewtonMeter>() + { { PowertrainPosition.HybridP2, 0.SI<NewtonMeter>() } }, + ShiftRequired = triggerGearshift, + NextGear = nextState.nextGear + }; }; strategy.InitializeFunc = (a, b) => new HybridStrategyResponse { MechanicalAssistPower = new Dictionary<PowertrainPosition, NewtonMeter>() { { PowertrainPosition.HybridP2, 0.SI<NewtonMeter>() } } }; + strategy.CommitFunc = () => { + currentState = nextState; + nextState = new StrategyState() { + lastGearShift = currentState.lastGearShift, + nextGear = currentState.nextGear, + }; + }; run.Run(); Assert.IsTrue(run.FinishedWithoutErrors); @@ -82,6 +107,13 @@ namespace TUGraz.VectoCore.Tests.Integration.Hybrid Assert.IsTrue(modData.Rows.Count > 0); } + public class StrategyState + { + public Second lastGearShift = -double.MaxValue.SI<Second>(); + public Second requestTstmp = -double.MaxValue.SI<Second>(); + public uint nextGear = 0u; + } + // ================================================= public static VectoRun CreateEngineeringRun(DrivingCycleData cycleData, string modFileName, double initialSoc, IHybridControlStrategy hybridStrategy, PowertrainPosition pos, bool largeMotor = false, SummaryDataContainer sumData = null, double pAuxEl = 0) -- GitLab