diff --git a/VectoCommon/VectoCommon/Models/HybridStrategyResponse.cs b/VectoCommon/VectoCommon/Models/HybridStrategyResponse.cs index 408ba98a65674a58dbd522fb9d92507f653e84bd..1545b0047453c4ec4af1fc1562e37069c1931225 100644 --- a/VectoCommon/VectoCommon/Models/HybridStrategyResponse.cs +++ b/VectoCommon/VectoCommon/Models/HybridStrategyResponse.cs @@ -17,7 +17,7 @@ namespace TUGraz.VectoCommon.Models { public class HybridStrategyResponse : AbstractComponentResponse, IHybridStrategyResponse { - public Dictionary<PowertrainPosition, NewtonMeter> MechanicalAssistPower; + public Dictionary<PowertrainPosition, Tuple<PerSecond, NewtonMeter>> MechanicalAssistPower; public bool ShiftRequired { get; set; } public uint NextGear { get; set; } public bool GearboxInNeutral { get; set; } diff --git a/VectoCore/VectoCore/Models/Connector/Ports/Impl/Response.cs b/VectoCore/VectoCore/Models/Connector/Ports/Impl/Response.cs index 64e25d64424b1b735be8ce74bd9ad95e4a091072..b2a4f086f23f97af51ba2ed16af77dcd94d857f5 100644 --- a/VectoCore/VectoCore/Models/Connector/Ports/Impl/Response.cs +++ b/VectoCore/VectoCore/Models/Connector/Ports/Impl/Response.cs @@ -199,6 +199,11 @@ namespace TUGraz.VectoCore.Models.Connector.Ports.Impl public ResponseDifferentGearEngaged(object source) : base(source) { } } + internal class ResponseInvalidOperatingPoint : AbstractResponse + { + public ResponseInvalidOperatingPoint(object source) : base(source) { } + } + /* internal class ResponseEngineSpeedTooLow : ResponseDryRun {} */ diff --git a/VectoCore/VectoCore/Models/Simulation/DataBus/IHybridControllerInfo.cs b/VectoCore/VectoCore/Models/Simulation/DataBus/IHybridControllerInfo.cs index ed12654306199174618751225756e1cd537a620f..daa2bb193cbc6162e27a665712f695f67903e3fa 100644 --- a/VectoCore/VectoCore/Models/Simulation/DataBus/IHybridControllerInfo.cs +++ b/VectoCore/VectoCore/Models/Simulation/DataBus/IHybridControllerInfo.cs @@ -1,9 +1,14 @@ -namespace TUGraz.VectoCore.Models.SimulationComponent +using TUGraz.VectoCommon.InputData; +using TUGraz.VectoCommon.Utils; + +namespace TUGraz.VectoCore.Models.SimulationComponent { public interface IHybridControllerInfo { GearInfo SelectedGear { get; } + PerSecond ElectricMotorSpeed(PowertrainPosition pos); + //IList<PowertrainPosition> ElectricMotors { get; } //NewtonMeter ElectricMotorTorque(PowertrainPosition pos); diff --git a/VectoCore/VectoCore/Models/SimulationComponent/IHybridControlStrategy.cs b/VectoCore/VectoCore/Models/SimulationComponent/IHybridControlStrategy.cs index 4560fb15350a598920995b2650ebb9a0210b1cc3..527e9ae2af0899d82c7720174e21b9ae762b59e2 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/IHybridControlStrategy.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/IHybridControlStrategy.cs @@ -21,5 +21,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent IHybridController Controller { set; } void WriteModalResults(Second time, Second simulationInterval, IModalDataContainer container); + void OperatingpointChangedDuringRequest(Second absTime, Second dt, NewtonMeter outTorque, + PerSecond outAngularVelocity, bool dryRun, IResponse retVal); } } \ No newline at end of file diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/ElectricMotor.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/ElectricMotor.cs index c8a187e6792faae524c05a2fae578194eb916080..ba8dc6bf0fdc5ab8d42771c32c814a4bf185690e 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/ElectricMotor.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/ElectricMotor.cs @@ -92,7 +92,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl if (!dryRun) { CurrentState.DragMax = maxRecuperationTorque; CurrentState.DriveMax = maxDriveTorque; - CurrentState.ElectricPowerToBattery = retVal.ElectricSystem.ConsumerPower; + CurrentState.ElectricPowerToBattery = retVal.ElectricSystem?.ConsumerPower; } return retVal; } @@ -191,12 +191,14 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl // return retVal; //} - if (!dryRun && (eMotorTorque.IsSmaller(maxDriveTorque ?? 0.SI<NewtonMeter>(), 1e-3) || eMotorTorque.IsGreater(maxRecuperationTorque ?? 0.SI<NewtonMeter>(), 1e-3)) - //!eMotorTorque.IsBetween( - // maxDriveTorque ?? 0.SI<NewtonMeter>(), maxRecuperationTorque ?? 0.SI<NewtonMeter>()) - ) { + if (!dryRun && (eMotorTorque.IsSmaller(maxDriveTorque ?? 0.SI<NewtonMeter>(), 1e-3) || + eMotorTorque.IsGreater(maxRecuperationTorque ?? 0.SI<NewtonMeter>(), 1e-3))) { + if (DataBus.HybridControllerInfo != null && !avgSpeed.IsEqual(DataBus.HybridControllerInfo.ElectricMotorSpeed(Position))) { + return new ResponseInvalidOperatingPoint(this); + } throw new VectoException( - "Invalid operating point provided by strategy! SupportPower: {0}, max Power: {1}, min Power: {2}", eMotorTorque, + "Invalid operating point provided by strategy! SupportPower: {0}, max Power: {1}, min Power: {2}", + eMotorTorque, maxDriveTorque, maxRecuperationTorque); } @@ -219,6 +221,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl // CurrentState.ElectricBrakePower = electricPower - electricSupplyResponse.MaxPowerDrag; //} if (!dryRun && !(electricSupplyResponse is ElectricSystemResponseSuccess)) { + if (DataBus.HybridControllerInfo != null && !avgSpeed.IsEqual(DataBus.HybridControllerInfo.ElectricMotorSpeed(Position))) { + return new ResponseInvalidOperatingPoint(this); + } throw new VectoException( "Invalid operating point provided by strategy! SupportPower: {0}, req. electric Power: {1}, battery demand motor: {3}, max Power from Battery: {2}", eMotorTorque, electricPower, diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/HybridController.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/HybridController.cs index 10a42b1d59645507feece266c87349d01a6e8a87..df264313617e78299b129101358500005a690cc5 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/HybridController.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/HybridController.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using TUGraz.VectoCommon.Exceptions; using TUGraz.VectoCommon.InputData; @@ -25,7 +26,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl protected readonly Dictionary<PowertrainPosition, ElectricMotorController> _electricMotorCtl; protected readonly HybridCtlShiftStrategy _shiftStrategy; protected readonly IHybridControlStrategy _hybridStrategy; - private Dictionary<PowertrainPosition, NewtonMeter> _electricMotorTorque = new Dictionary<PowertrainPosition, NewtonMeter>(); + private Dictionary<PowertrainPosition, Tuple<PerSecond, NewtonMeter>> _electricMotorTorque = new Dictionary<PowertrainPosition, Tuple<PerSecond, NewtonMeter>>(); + private HybridStrategyResponse CurrentStrategySettings; public HybridController(IVehicleContainer container, IHybridControlStrategy strategy, IElectricSystem es, @@ -90,6 +92,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl public GearInfo SelectedGear { get; protected set; } + public PerSecond ElectricMotorSpeed(PowertrainPosition pos) + { + return CurrentStrategySettings.MechanicalAssistPower[pos].Item1; + } + public IResponse Request(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, bool dryRun = false) @@ -127,10 +134,23 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return new ResponseGearShift(this); } + if (!dryRun && DataBus.VehicleInfo.VehicleStopped) { + SelectedGear = new GearInfo(strategySettings.NextGear, true); + } + + CurrentStrategySettings = strategySettings; retVal = NextComponent.Request(absTime, dt, outTorque, outAngularVelocity, dryRun); if (retVal is ResponseDifferentGearEngaged) { retryCount++; retry = true; + Strategy.OperatingpointChangedDuringRequest(absTime, dt, outTorque, outAngularVelocity, dryRun, retVal); + continue; + } + + if (retVal is ResponseInvalidOperatingPoint) { + retryCount++; + retry = true; + Strategy.OperatingpointChangedDuringRequest(absTime, dt, outTorque, outAngularVelocity, dryRun, retVal); continue; } retVal.HybridController.StrategySettings = strategySettings; @@ -173,7 +193,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl private NewtonMeter MechanicalAssistPower(PowertrainPosition pos, Second absTime, Second dt, NewtonMeter outTorque, PerSecond prevOutAngularVelocity, PerSecond currOutAngularVelocity, bool dryRun) { - return _electricMotorTorque[pos]; + return _electricMotorTorque[pos]?.Item2; //return CurrentState.StrategyResponse.MechanicalAssistPower[pos]; } diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/SimpleHybridController.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/SimpleHybridController.cs index 44eaaee5f8557e0e5520a6e0cb500dbef9c761c8..1f355d7e9c0c44c8920cd31a860e2088633a0028 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/SimpleHybridController.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/SimpleHybridController.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using TUGraz.VectoCommon.Exceptions; using TUGraz.VectoCommon.InputData; using TUGraz.VectoCommon.Models; @@ -19,7 +20,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { protected readonly Dictionary<PowertrainPosition, ElectricMotorController> _electricMotorCtl = new Dictionary<PowertrainPosition, ElectricMotorController>(); public ITnOutPort NextComponent; - private Dictionary<PowertrainPosition, NewtonMeter> _electricMotorTorque = new Dictionary<PowertrainPosition, NewtonMeter>(); + private Dictionary<PowertrainPosition, Tuple<PerSecond, NewtonMeter>> _electricMotorTorque = new Dictionary<PowertrainPosition, Tuple<PerSecond, NewtonMeter>>(); public SimpleHybridController(VehicleContainer container, ElectricSystem es, SwitchableClutch clutch) : base(container) { @@ -131,7 +132,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { private NewtonMeter MechanicalAssistPower(PowertrainPosition pos, Second absTime, Second dt, NewtonMeter outTorque, PerSecond prevOutAngularVelocity, PerSecond currOutAngularVelocity, bool dryRun) { - return _electricMotorTorque.ContainsKey(pos) ? _electricMotorTorque[pos] : null; + return _electricMotorTorque.ContainsKey(pos) ? _electricMotorTorque[pos].Item2 : null; } ///======================================================================================= @@ -179,5 +180,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { public GearInfo SelectedGear { get; } + public PerSecond ElectricMotorSpeed(PowertrainPosition pos) + { + return null; + } } } \ 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 20248584db125e52aa070e7f88d83371bd9db77f..cf47ad98d90ea7ea7cb8b08911bfa997ca294d9c 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Strategies/HybridStrategy.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Strategies/HybridStrategy.cs @@ -56,7 +56,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies private VectoRunData ModelData; private IDataBus DataBus; - protected Dictionary<PowertrainPosition, NewtonMeter> ElectricMotorsOff; + protected Dictionary<PowertrainPosition, Tuple<PerSecond, NewtonMeter>> ElectricMotorsOff; private bool ElectricMotorCanPropellDuringTractionInterruption; @@ -93,7 +93,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies ElectricMotorsOff = ModelData.ElectricMachinesData .Select(x => new KeyValuePair<PowertrainPosition, NewtonMeter>(x.Item1, null)) - .ToDictionary(x => x.Key, x => x.Value); + .ToDictionary(x => x.Key, x => new Tuple<PerSecond, NewtonMeter>(null, x.Value)); var emPos = ModelData.ElectricMachinesData.First().Item1; ElectricMotorCanPropellDuringTractionInterruption = emPos == PowertrainPosition.HybridP4 || emPos == PowertrainPosition.HybridP3; @@ -153,17 +153,19 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies public virtual IHybridStrategyResponse Request(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, bool dryRun) { - if (DataBus.DriverInfo.DrivingAction == DrivingAction.Accelerate && (outTorque * outAngularVelocity).IsGreater(StrategyParameters.MaxDrivetrainPower, Constants.SimulationSettings.LineSearchTolerance)) { + if (DataBus.DriverInfo.DrivingAction == DrivingAction.Accelerate && + (outTorque * outAngularVelocity).IsGreater(StrategyParameters.MaxDrivetrainPower, + Constants.SimulationSettings.LineSearchTolerance)) { return HandleRequestExceedsMaxPower(absTime, dt, outTorque, outAngularVelocity, dryRun); } var currentGear = PreviousState.GearboxEngaged ? DataBus.GearboxInfo.Gear : Controller.ShiftStrategy.NextGear.Gear; - //if (DryRunSolution != null && DryRunSolution.DrivingAction == DataBus.DriverInfo.DrivingAction) { - // return CreateResponse(DryRunSolution.Solution, currentGear); - //} + if (DryRunSolution != null && DryRunSolution.DrivingAction == DataBus.DriverInfo.DrivingAction) { + return CreateResponse(DryRunSolution.Solution, currentGear); + } - if (DryRunSolution != null && DryRunSolution.DrivingAction != DataBus.DriverInfo.DrivingAction) { + if (DryRunSolution != null && DryRunSolution.DrivingAction != DataBus.DriverInfo.DrivingAction) { DryRunSolution = null; } @@ -246,6 +248,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies return response; } + public void OperatingpointChangedDuringRequest(Second absTime, Second dt, NewtonMeter outTorque, + PerSecond outAngularVelocity, + bool dryRun, IResponse retVal) + { + DryRunSolution = null; + } + private IHybridStrategyResponse HandleRequestExceedsMaxPower(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, bool dryRun) { // issue dry-run to get max available power from EM and ICE, @@ -267,8 +276,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies var maxEmDriveSetting = new HybridStrategyResponse() { CombustionEngineOn = true, GearboxInNeutral = false, - MechanicalAssistPower = new Dictionary<PowertrainPosition, NewtonMeter>() { - {emPos ,emOffResponse.ElectricMotor.MaxDriveTorque} + MechanicalAssistPower = new Dictionary<PowertrainPosition, Tuple<PerSecond ,NewtonMeter>>() { + {emPos , Tuple.Create(emOffResponse.ElectricMotor.AngularVelocity, emOffResponse.ElectricMotor.MaxDriveTorque)} }, }; var maxEmDriveResponse = @@ -391,8 +400,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies var maxRecuperation = new HybridStrategyResponse() { CombustionEngineOn = DataBus.EngineInfo.EngineOn, // AllowICEOff(absTime), GearboxInNeutral = false, - MechanicalAssistPower = new Dictionary<PowertrainPosition, NewtonMeter>() { - { emPos, firstResponse.ElectricMotor.MaxRecuperationTorque } + MechanicalAssistPower = new Dictionary<PowertrainPosition, Tuple<PerSecond, NewtonMeter>>() { + { emPos, Tuple.Create(firstResponse.ElectricMotor.AngularVelocity, firstResponse.ElectricMotor.MaxRecuperationTorque) } } }; var maxRecuperationResponse = RequestDryRun( @@ -407,8 +416,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies Setting = new HybridStrategyResponse() { CombustionEngineOn = DataBus.EngineInfo.EngineOn, GearboxInNeutral = false, - MechanicalAssistPower = new Dictionary<PowertrainPosition, NewtonMeter>() { - { emPos, firstResponse.ElectricMotor.MaxRecuperationTorque } + MechanicalAssistPower = new Dictionary<PowertrainPosition, Tuple<PerSecond, NewtonMeter>>() { + { emPos, Tuple.Create(firstResponse.ElectricMotor.AngularVelocity, firstResponse.ElectricMotor.MaxRecuperationTorque) } } } }); @@ -428,8 +437,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies var cfg = new HybridStrategyResponse() { CombustionEngineOn = DataBus.EngineInfo.EngineOn, GearboxInNeutral = false, - MechanicalAssistPower = new Dictionary<PowertrainPosition, NewtonMeter>() { - { emPos, emTq } + MechanicalAssistPower = new Dictionary<PowertrainPosition, Tuple<PerSecond, NewtonMeter>>() { + { emPos, Tuple.Create(firstResponse.ElectricMotor.AngularVelocity, emTq) } } }; return RequestDryRun(absTime, dt, outTorque, outAngularVelocity, DataBus.GearboxInfo.GearEngaged(absTime) ? currentGear : 0, cfg); @@ -446,8 +455,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies Setting = new HybridStrategyResponse() { CombustionEngineOn = DataBus.EngineInfo.EngineOn, GearboxInNeutral = false, - MechanicalAssistPower = new Dictionary<PowertrainPosition, NewtonMeter>() { - { emPos, emRecuperationTq } + MechanicalAssistPower = new Dictionary<PowertrainPosition, Tuple<PerSecond, NewtonMeter>>() { + { emPos, Tuple.Create(firstResponse.ElectricMotor.AngularVelocity, emRecuperationTq) } } } }; @@ -461,8 +470,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies Setting = new HybridStrategyResponse() { CombustionEngineOn = DataBus.EngineInfo.EngineOn, GearboxInNeutral = false, - MechanicalAssistPower = new Dictionary<PowertrainPosition, NewtonMeter>() { - { emPos, firstResponse.ElectricMotor.MaxRecuperationTorque } + MechanicalAssistPower = new Dictionary<PowertrainPosition, Tuple<PerSecond, NewtonMeter>>() { + { emPos, Tuple.Create(firstResponse.ElectricMotor.AngularVelocity, firstResponse.ElectricMotor.MaxRecuperationTorque) } } } }); @@ -588,7 +597,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies .OrderBy(x => Math.Abs((int)currentGear - x.Gear)).ToArray(); if (filtered.Length > 0) { best = filtered.OrderBy(x => Math.Abs((int)currentGear - x.Gear)) - .ThenBy(x => x.Setting.MechanicalAssistPower.Sum(e => e.Value ?? 0.SI<NewtonMeter>())) + .ThenBy(x => x.Setting.MechanicalAssistPower.Sum(e => e.Value?.Item2 ?? 0.SI<NewtonMeter>())) .FirstOrDefault(); //.MinBy( //..x => x.Setting.MechanicalAssistPower.Sum(e => e.Value ?? 0.SI<NewtonMeter>())); @@ -607,7 +616,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies if (!filtered.Any()) { filtered = eval.OrderBy(x => Math.Abs((int)currentGear - x.Gear)).ToArray(); } - best = filtered.Where(x => !x.IgnoreReason.BatteryDemandExceeded()).MaxBy(x => x.Setting.MechanicalAssistPower.Sum(e => e.Value ?? 0.SI<NewtonMeter>())); + best = filtered.Where(x => !x.IgnoreReason.BatteryDemandExceeded()).MaxBy(x => x.Setting.MechanicalAssistPower.Sum(e => e.Value?.Item2 ?? 0.SI<NewtonMeter>())); if (best != null) { return best; } @@ -631,13 +640,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies if (filtered2.Length == 0) { filtered2 = filtered.OrderBy(x => Math.Abs((int)currentGear - x.Gear)).ToArray(); } - best = filtered2.MinBy(x => x.Setting.MechanicalAssistPower.Sum(e => e.Value ?? 0.SI<NewtonMeter>())); + best = filtered2.MinBy(x => x.Setting.MechanicalAssistPower.Sum(e => e.Value?.Item2 ?? 0.SI<NewtonMeter>())); if (best != null) { return best; } } if (DataBus.DriverInfo.DrivingAction == DrivingAction.Brake && emEngaged) { - best = eval.Where(x => !x.IgnoreReason.BatteryDemandExceeded()).MaxBy(x => x.Setting.MechanicalAssistPower.Sum(e => e.Value ?? 0.SI<NewtonMeter>())); + best = eval.Where(x => !x.IgnoreReason.BatteryDemandExceeded()).MaxBy(x => x.Setting.MechanicalAssistPower.Sum(e => e.Value?.Item2 ?? 0.SI<NewtonMeter>())); if (best != null) { return best; } @@ -665,10 +674,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies if (filtered.Length == 0) { filtered = eval.OrderBy(x => Math.Abs((int)currentGear - x.Gear)).ToArray(); } - best = filtered.MinBy(x => x.Setting.MechanicalAssistPower.Sum(e => e.Value ?? 0.SI<NewtonMeter>())); + best = filtered.MinBy(x => x.Setting.MechanicalAssistPower.Sum(e => e.Value?.Item2 ?? 0.SI<NewtonMeter>())); } if (DataBus.DriverInfo.DrivingAction == DrivingAction.Brake && emEngaged) { - best = eval.MaxBy(x => x.Setting.MechanicalAssistPower.Sum(e => e.Value ?? 0.SI<NewtonMeter>())); + best = eval.MaxBy(x => x.Setting.MechanicalAssistPower.Sum(e => e.Value?.Item2 ?? 0.SI<NewtonMeter>())); } } if (best == null) { @@ -689,7 +698,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies .ThenBy(x => -x.Response.ElectricSystem.RESSPowerDemand.Value()).First(); } else { best = filtered.MinBy( - x => x.Setting.MechanicalAssistPower.Sum(e => e.Value ?? 0.SI<NewtonMeter>())); + x => x.Setting.MechanicalAssistPower.Sum(e => e.Value?.Item2 ?? 0.SI<NewtonMeter>())); } } } @@ -702,7 +711,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies filtered = eval.OrderBy(x => Math.Abs((int)currentGear - x.Gear)).ToArray(); } best = filtered.MaxBy( - x => x.Setting.MechanicalAssistPower.Sum(e => e.Value ?? 0.SI<NewtonMeter>())); + x => x.Setting.MechanicalAssistPower.Sum(e => e.Value?.Item2 ?? 0.SI<NewtonMeter>())); } } } else { @@ -768,7 +777,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies var emPos = ModelData.ElectricMachinesData.First().Item1; var emTorque = !ElectricMotorCanPropellDuringTractionInterruption && (firstResponse.Gearbox.Gear == 0 || !DataBus.GearboxInfo.GearEngaged(absTime)) ? null : firstResponse.ElectricMotor.MaxRecuperationTorque; - return TryConfiguration(absTime, dt, outTorque, outAngularVelocity, currentGear, emPos, emTorque, double.NaN, AllowICEOff(absTime), dryRun); + return TryConfiguration(absTime, dt, outTorque, outAngularVelocity, currentGear, emPos, Tuple.Create(firstResponse.ElectricMotor.AngularVelocity, emTorque), double.NaN, AllowICEOff(absTime), dryRun); } private List<HybridResultEntry> FindSolution(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, bool dryRun) @@ -920,7 +929,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies continue; } - var tmp = TryConfiguration(absTime, dt, outTorque, outAngularVelocity, nextGear, emPos, emTorque, u, allowIceOff, dryRun); + var tmp = TryConfiguration(absTime, dt, outTorque, outAngularVelocity, nextGear, emPos, Tuple.Create(firstResponse.ElectricMotor.AngularVelocity, emTorque), u, allowIceOff, dryRun); responses.Add(tmp); } @@ -930,11 +939,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies var emTorqueM = emTqReq * maxU; if (!responses.Any(x => x.Gear == nextGear && x.U.IsEqual(maxU)) && emTorqueM.IsBetween( 0.SI<NewtonMeter>(), firstResponse.ElectricMotor.MaxDriveTorque)) { - var tmp = TryConfiguration(absTime, dt, outTorque, outAngularVelocity, nextGear, emPos, emTorqueM, maxU, allowIceOff, dryRun); + var tmp = TryConfiguration(absTime, dt, outTorque, outAngularVelocity, nextGear, emPos, Tuple.Create(firstResponse.ElectricMotor.AngularVelocity, emTorqueM), maxU, allowIceOff, dryRun); responses.Add(tmp); } if (maxEmTorque.IsSmaller(0) && emTqReq.IsGreater(-maxEmTorque)) { - var tmp = TryConfiguration(absTime, dt, outTorque, outAngularVelocity, nextGear, emPos, maxEmTorque, maxEmTorque / emTqReq, allowIceOff, dryRun); + var tmp = TryConfiguration(absTime, dt, outTorque, outAngularVelocity, nextGear, emPos, Tuple.Create(firstResponse.ElectricMotor.AngularVelocity, maxEmTorque), maxEmTorque / emTqReq, allowIceOff, dryRun); if (!tmp.Response.ElectricSystem.ConsumerPower.IsSmaller(emDrivePower)) { responses.Add(tmp); } @@ -953,7 +962,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies firstResponse.ElectricMotor.MaxRecuperationTorque, firstResponse.ElectricMotor.MaxDriveTorque) && !emDriveTorque.IsEqual(emDragTorque, 1.SI<NewtonMeter>())) { var tmp = TryConfiguration( - absTime, dt, outTorque, outAngularVelocity, nextGear, emPos, emDriveTorque, emDriveTorque / emTqReq, + absTime, dt, outTorque, outAngularVelocity, nextGear, emPos, Tuple.Create(firstResponse.ElectricMotor.AngularVelocity, emDriveTorque), emDriveTorque / emTqReq, allowIceOff, dryRun); responses.Add(tmp); } @@ -974,8 +983,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies var cfg = new HybridStrategyResponse() { CombustionEngineOn = true, GearboxInNeutral = false, - MechanicalAssistPower = new Dictionary<PowertrainPosition, NewtonMeter>() { - { emPos, emTq } + MechanicalAssistPower = new Dictionary<PowertrainPosition, Tuple<PerSecond, NewtonMeter>>() { + { emPos, Tuple.Create(firstResponse.ElectricMotor.AngularVelocity, emTq) } } }; return RequestDryRun(absTime, dt, outTorque, outAngularVelocity, nextGear, cfg); @@ -989,7 +998,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies firstResponse.ElectricMotor.MaxDriveTorque, firstResponse.ElectricMotor.MaxRecuperationTorque)) { // only consider when within allowed EM torque range var tmp = TryConfiguration( - absTime, dt, outTorque, outAngularVelocity, nextGear, emPos, emTorqueICEOff, emTorqueICEOff / emTqReq, + absTime, dt, outTorque, outAngularVelocity, nextGear, emPos, Tuple.Create(firstResponse.ElectricMotor.AngularVelocity, emTorqueICEOff), emTorqueICEOff / emTqReq, allowIceOff, dryRun); responses.Add(tmp); } @@ -1008,7 +1017,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies continue; } - var tmp = TryConfiguration(absTime, dt, outTorque, outAngularVelocity, nextGear, emPos, emTorque, u, allowIceOff, dryRun); + var tmp = TryConfiguration(absTime, dt, outTorque, outAngularVelocity, nextGear, emPos, Tuple.Create(firstResponse.ElectricMotor.AngularVelocity, emTorque), u, allowIceOff, dryRun); responses.Add(tmp); } var maxEmTorqueRecuperate = firstResponse.ElectricMotor.MaxRecuperationTorque ?? 0.SI<NewtonMeter>(); @@ -1029,8 +1038,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies var cfg = new HybridStrategyResponse() { CombustionEngineOn = true, GearboxInNeutral = false, - MechanicalAssistPower = new Dictionary<PowertrainPosition, NewtonMeter>() { - { emPos, emTq } + MechanicalAssistPower = new Dictionary<PowertrainPosition, Tuple<PerSecond, NewtonMeter>>() { + { emPos, Tuple.Create(firstResponse.ElectricMotor.AngularVelocity, emTq) } } }; return RequestDryRun(absTime, dt, outTorque, outAngularVelocity, nextGear, cfg); @@ -1043,7 +1052,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies if (emTorqueICEOff.IsBetween(maxEmTorqueRecuperate, 0.SI<NewtonMeter>())) { // only consider where EM is recuperating var tmp = TryConfiguration( - absTime, dt, outTorque, outAngularVelocity, nextGear, emPos, emTorqueICEOff, + absTime, dt, outTorque, outAngularVelocity, nextGear, emPos, Tuple.Create(firstResponse.ElectricMotor.AngularVelocity, emTorqueICEOff), emTorqueICEOff / maxEmTorqueRecuperate, allowIceOff, dryRun); responses.Add(tmp); @@ -1054,7 +1063,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies } else { if (maxEmTorqueRecuperate.IsGreater(0) && (-emTqReq).IsBetween(maxEmTorqueRecuperate, 0.SI<NewtonMeter>())) { var tmp = TryConfiguration(absTime, dt, outTorque, outAngularVelocity, nextGear, emPos, - -emTqReq, -emTqReq / maxEmTorqueRecuperate, allowIceOff, dryRun); + Tuple.Create(firstResponse.ElectricMotor.AngularVelocity, -emTqReq), -emTqReq / maxEmTorqueRecuperate, allowIceOff, dryRun); responses.Add(tmp); } } @@ -1063,14 +1072,14 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies } private HybridResultEntry TryConfiguration(Second absTime, Second dt, NewtonMeter outTorque, - PerSecond outAngularVelocity, uint nextGear, PowertrainPosition emPos, NewtonMeter emTorque, double u, + PerSecond outAngularVelocity, uint nextGear, PowertrainPosition emPos, Tuple<PerSecond, NewtonMeter> emTorque, double u, bool allowIceOff, bool dryRun) { var cfg = new HybridStrategyResponse() { CombustionEngineOn = true, GearboxInNeutral = false, - MechanicalAssistPower = new Dictionary<PowertrainPosition, NewtonMeter>() { - { emPos, emTorque } + MechanicalAssistPower = new Dictionary<PowertrainPosition, Tuple<PerSecond, NewtonMeter>>() { + { emPos, emTorque } } }; var resp = RequestDryRun(absTime, dt, outTorque, outAngularVelocity, nextGear, cfg); @@ -1081,6 +1090,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies Response = resp, Gear = nextGear, }; + CalcualteCosts(resp, dt, tmp, allowIceOff, dryRun); return tmp; } @@ -1115,10 +1125,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies var vDrop = DataBus.VehicleInfo.VehicleSpeed - estimatedVelocityPostShift; - var vehicleSpeedPostShift = DataBus.VehicleInfo.VehicleSpeed - vDrop * ModelData.GearshiftParameters.VelocityDropFactor; + var vehicleSpeedPostShift = estimatedVelocityPostShift; // DataBus.VehicleInfo.VehicleSpeed - vDrop * ModelData.GearshiftParameters.VelocityDropFactor; TestPowertrain.Gearbox.Gear = nextGear; - TestPowertrain.Container.VehiclePort.Initialize( + var init = TestPowertrain.Container.VehiclePort.Initialize( vehicleSpeedPostShift, DataBus.DrivingCycleInfo.RoadGradient ?? 0.SI<Radian>()); + if (init.Engine.EngineSpeed.IsSmaller(ModelData.EngineData.IdleSpeed)) { + return null; + } } if (nextGear == 0) { @@ -1325,7 +1338,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Strategies public virtual IHybridStrategyResponse Initialize(NewtonMeter outTorque, PerSecond outAngularVelocity) { var retVal = new HybridStrategyResponse() - { MechanicalAssistPower = new Dictionary<PowertrainPosition, NewtonMeter>() }; + { MechanicalAssistPower = new Dictionary<PowertrainPosition, Tuple<PerSecond, NewtonMeter>>() }; foreach (var em in ModelData.ElectricMachinesData) { retVal.MechanicalAssistPower[em.Item1] = null; diff --git a/VectoCore/VectoCoreTest/Integration/Hybrid/ParallelHybridTest.cs b/VectoCore/VectoCoreTest/Integration/Hybrid/ParallelHybridTest.cs index 880f6ea8c506b8c7c201d23c63ced97e913ad4d8..ba8abfcd19e41dc0b87bff4211fc98668c68d298 100644 --- a/VectoCore/VectoCoreTest/Integration/Hybrid/ParallelHybridTest.cs +++ b/VectoCore/VectoCoreTest/Integration/Hybrid/ParallelHybridTest.cs @@ -343,7 +343,7 @@ namespace TUGraz.VectoCore.Tests.Integration.Hybrid TestCase(Group5TestJob325kW, 2, TestName = "P2 Hybrid Group 5 325kW DriveCycle Construction"), TestCase(Group5TestJob325kW, 3, TestName = "P2 Hybrid Group 5 325kW DriveCycle HeavyUrban"), TestCase(Group5TestJob325kW, 4, TestName = "P2 Hybrid Group 5 325kW DriveCycle Interurban"), // error - TestCase(Group5TestJob325kW, 5, TestName = "P2 Hybrid Group 5 325kW Dr40/iveCycle MunicipalUtility"), + TestCase(Group5TestJob325kW, 5, TestName = "P2 Hybrid Group 5 325kW DriveCycle MunicipalUtility"), TestCase(Group5TestJob325kW, 6, TestName = "P2 Hybrid Group 5 325kW DriveCycle RegionalDelivery"), TestCase(Group5TestJob325kW, 7, TestName = "P2 Hybrid Group 5 325kW DriveCycle Suburban"), TestCase(Group5TestJob325kW, 8, TestName = "P2 Hybrid Group 5 325kW DriveCycle Urban"),