diff --git a/VectoCommon/VectoCommon/Models/PowertrainPosition.cs b/VectoCommon/VectoCommon/Models/PowertrainPosition.cs index 2c36ab7b789fef199140fc9664500c04bbb5183e..0f67189569e097355af22185139cb3607ad7600a 100644 --- a/VectoCommon/VectoCommon/Models/PowertrainPosition.cs +++ b/VectoCommon/VectoCommon/Models/PowertrainPosition.cs @@ -8,7 +8,11 @@ namespace TUGraz.VectoCommon.InputData { HybridP1, HybridP2, HybridP3, - HybridP4 + HybridP4, + + BatteryElectricB4, + BatteryElectricB3, + BatteryElectricB2, } public static class PowertrainPositionHelper diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/BatteryElectricMotorController.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/BatteryElectricMotorController.cs new file mode 100644 index 0000000000000000000000000000000000000000..70ab19bc429113a93bf2fef219ea6694dbb601f3 --- /dev/null +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/BatteryElectricMotorController.cs @@ -0,0 +1,28 @@ +using TUGraz.VectoCommon.InputData; +using TUGraz.VectoCommon.Utils; +using TUGraz.VectoCore.Models.Simulation.Impl; + +namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { + public class BatteryElectricMotorController : IElectricMotorControl + { + private VehicleContainer DataBus; + private ElectricSystem ElectricSystem; + + public BatteryElectricMotorController(VehicleContainer container, ElectricSystem es) + { + DataBus = container; + ElectricSystem = es; + } + + #region Implementation of IElectricMotorControl + + public NewtonMeter MechanicalAssistPower( + Second absTime, Second dt, NewtonMeter outTorque, PerSecond prevOutAngularVelocity, PerSecond currOutAngularVelocity, + PowertrainPosition position, bool dryRun) + { + throw new System.NotImplementedException(); + } + + #endregion + } +} \ No newline at end of file diff --git a/VectoCore/VectoCore/VectoCore.csproj b/VectoCore/VectoCore/VectoCore.csproj index 264729c31bc6fa40655bb09d8d5be3e748b64e44..448800c4c9dcc4d54c24b6b752a75f27a9174fa2 100644 --- a/VectoCore/VectoCore/VectoCore.csproj +++ b/VectoCore/VectoCore/VectoCore.csproj @@ -398,6 +398,7 @@ <Compile Include="Models\SimulationComponent\IHybridControlledGearbox.cs" /> <Compile Include="Models\SimulationComponent\IHybridControlStrategy.cs" /> <Compile Include="Models\SimulationComponent\Impl\Battery.cs" /> + <Compile Include="Models\SimulationComponent\Impl\BatteryElectricMotorController.cs" /> <Compile Include="Models\SimulationComponent\Impl\ElectricAuxiliary.cs" /> <Compile Include="Models\SimulationComponent\Impl\ElectricMotor.cs" /> <Compile Include="Models\SimulationComponent\Impl\HybridController.cs" /> diff --git a/VectoCore/VectoCoreTest/Integration/BatteryElectric/BatteryElectricTest.cs b/VectoCore/VectoCoreTest/Integration/BatteryElectric/BatteryElectricTest.cs new file mode 100644 index 0000000000000000000000000000000000000000..33d8916379b03a3ca65956fdb7d503acd8232bc2 --- /dev/null +++ b/VectoCore/VectoCoreTest/Integration/BatteryElectric/BatteryElectricTest.cs @@ -0,0 +1,382 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using NUnit.Framework; +using TUGraz.VectoCommon.BusAuxiliaries; +using TUGraz.VectoCommon.Exceptions; +using TUGraz.VectoCommon.InputData; +using TUGraz.VectoCommon.Models; +using TUGraz.VectoCommon.Utils; +using TUGraz.VectoCore.InputData.Impl; +using TUGraz.VectoCore.InputData.Reader.ComponentData; +using TUGraz.VectoCore.Models.Declaration; +using TUGraz.VectoCore.Models.Simulation.Data; +using TUGraz.VectoCore.Models.Simulation.Impl; +using TUGraz.VectoCore.Models.SimulationComponent; +using TUGraz.VectoCore.Models.SimulationComponent.Data; +using TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox; +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.Utils; +using TUGraz.VectoCore.Utils; +using ElectricSystem = TUGraz.VectoCore.Models.SimulationComponent.ElectricSystem; + + +namespace TUGraz.VectoCore.Tests.Integration.BatteryElectric +{ + [TestFixture] + public class BatteryElectricTest + { + + + + private ModalResultField[] Yfields; + public const string MotorFile = @"TestData\Hybrids\ElectricMotor\GenericEMotor.vem"; + public const string BatFile = @"TestData\Hybrids\Battery\GenericBattery.vbat"; + + public const string AccelerationFile = @"TestData\Components\Truck.vacc"; + public const string MotorFile240kW = @"TestData\Hybrids\ElectricMotor\GenericEMotor240kW.vem"; + + public const string GearboxIndirectLoss = @"TestData\Components\Indirect Gear.vtlm"; + public const string GearboxDirectLoss = @"TestData\Components\Direct Gear.vtlm"; + + [OneTimeSetUp] + public void RunBeforeAnyTests() + { + Directory.SetCurrentDirectory(TestContext.CurrentContext.TestDirectory); + + InitGraphWriter(); + } + + + private void InitGraphWriter() + { + //#if TRACE + GraphWriter.Enable(); + + //#else + //GraphWriter.Disable(); + //#endif + GraphWriter.Xfields = new[] { ModalResultField.dist }; + + Yfields = new[] { + ModalResultField.v_act, ModalResultField.altitude, ModalResultField.acc, ModalResultField.Gear, + ModalResultField.P_ice_out, ModalResultField.BatterySOC, ModalResultField.FCMap + }; + GraphWriter.Series1Label = "Hybrid"; + GraphWriter.PlotIgnitionState = true; + } + + + [ + TestCase(30, 0.7, 0, TestName = "B4 Hybrid DriveOff 30km/h SoC: 0.7, level"), + TestCase(80, 0.7, 0, TestName = "B4 Hybrid DriveOff 80km/h SoC: 0.7, level"), + TestCase(30, 0.25, 0, TestName = "B4 Hybrid DriveOff 30km/h SoC: 0.25, level") + ] + public void B4HybridDriveOff(double vmax, double initialSoC, double slope) + { + GraphWriter.Yfields = Yfields.Concat(new[] { ModalResultField.P_electricMotor_mech_P2 }).ToArray(); + var cycleData = string.Format( + @" 0, 0, {1}, 3 + 700, {0}, {1}, 0", vmax, slope); + var cycle = SimpleDrivingCycles.CreateCycleData(cycleData); + + const bool largeMotor = true; + + var modFilename = string.Format("SimpleBatteryElectric-B4_acc_{0}-{1}_{2}.vmod", vmax, initialSoC, slope); + const PowertrainPosition pos = PowertrainPosition.BatteryElectricB4; + var run = CreateEngineeringRun( + cycle, modFilename, initialSoC, pos, largeMotor: true); + + var hybridController = (HybridController)((VehicleContainer)run.GetContainer()).HybridController; + Assert.NotNull(hybridController); + + var modData = ((ModalDataContainer)((VehicleContainer)run.GetContainer()).ModData).Data; + + run.Run(); + Assert.IsTrue(run.FinishedWithoutErrors); + + Assert.IsTrue(modData.Rows.Count > 0); + GraphWriter.Write(modFilename); + } + + // ================================================= + + + public static VectoRun CreateEngineeringRun( + DrivingCycleData cycleData, string modFileName, double initialSoc, PowertrainPosition pos, bool largeMotor = false, + SummaryDataContainer sumData = null, double pAuxEl = 0, Kilogram payload = null) + { + var container = CreateBatteryElectricPowerTrain( + cycleData, Path.GetFileNameWithoutExtension(modFileName), initialSoc, largeMotor, sumData, pAuxEl, pos, payload); + return new DistanceRun(container); + } + + public static VehicleContainer CreateBatteryElectricPowerTrain(DrivingCycleData cycleData, string modFileName, + double initialBatCharge, bool largeMotor, SummaryDataContainer sumData, double pAuxEl, PowertrainPosition pos, Kilogram payload = null) + { + var fileWriter = new FileOutputWriter(modFileName); + var modDataFilter = new IModalDataFilter[] { }; //new IModalDataFilter[] { new ActualModalDataFilter(), }; + var modData = new ModalDataContainer( + modFileName, new IFuelProperties[] { FuelData.Diesel }, fileWriter, + filters: modDataFilter) { + WriteModalResults = true, + }; + + var gearboxData = CreateGearboxData(); + var axleGearData = CreateAxleGearData(); + + var vehicleData = CreateVehicleData(payload ?? 3300.SI<Kilogram>()); + var airdragData = CreateAirdragData(); + var driverData = CreateDriverData(AccelerationFile, true); + + var electricMotorData = + MockSimulationDataFactory.CreateElectricMotorData(largeMotor ? MotorFile240kW : MotorFile, pos); + + var batteryData = MockSimulationDataFactory.CreateBatteryData(BatFile, initialBatCharge); + + var engineData = MockSimulationDataFactory.CreateEngineDataFromFile( + Truck40tPowerTrain.EngineFile, gearboxData.Gears.Count); + + foreach (var entry in gearboxData.Gears) { + entry.Value.ShiftPolygon = DeclarationData.Gearbox.ComputeEfficiencyShiftPolygon( + (int)entry.Key, engineData.FullLoadCurves[entry.Key], new TransmissionInputData().Repeat(gearboxData.Gears.Count + 1).Cast<ITransmissionInputData>().ToList(), engineData, axleGearData.AxleGear.Ratio, + vehicleData.DynamicTyreRadius); + } + + var runData = new VectoRunData() { + JobRunId = 0, + DriverData = driverData, + AxleGearData = axleGearData, + GearboxData = gearboxData, + VehicleData = vehicleData, + AirdragData = airdragData, + JobName = modFileName, + Cycle = cycleData, + Retarder = new RetarderData() { Type = RetarderType.None }, + Aux = new List<VectoRunData.AuxData>(), + ElectricMachinesData = electricMotorData, + EngineData = engineData, + BatteryData = batteryData, + GearshiftParameters = CreateGearshiftData(gearboxData, axleGearData.AxleGear.Ratio, engineData.IdleSpeed), + ElectricAuxDemand = pAuxEl.SI<Watt>() + }; + var container = new VehicleContainer( + ExecutionMode.Engineering, modData, x => { sumData?.Write(x, 1, 1, runData); }); + container.RunData = runData; + + var es = new ElectricSystem(container); + var battery = new Battery(container, batteryData); + battery.Initialize(initialBatCharge); + + var ctl = new BatteryElectricMotorController(container, es); + + es.Connect(battery); + + var cycle = new DistanceBasedDrivingCycle(container, cycleData); + + var aux = new ElectricAuxiliary(container); + aux.AddConstant("P_aux_el", pAuxEl.SI<Watt>()); + es.Connect(aux); + + var powertrain = cycle + .AddComponent(new Driver(container, runData.DriverData, new DefaultDriverStrategy(container))) + .AddComponent(new Vehicle(container, runData.VehicleData, runData.AirdragData)) + .AddComponent(new VectoCore.Models.SimulationComponent.Impl.Wheels(container, runData.VehicleData.DynamicTyreRadius, + runData.VehicleData.WheelsInertia)) + .AddComponent(new Brakes(container)); + + switch (pos) { + case PowertrainPosition.HybridPositionNotSet: + throw new VectoException("invalid powertrain position"); + case PowertrainPosition.HybridP0: + case PowertrainPosition.HybridP1: + case PowertrainPosition.HybridP2: + case PowertrainPosition.HybridP3: + case PowertrainPosition.HybridP4: + throw new VectoException("testcase does not support parallel powertrain configurations"); + case PowertrainPosition.BatteryElectricB4: + powertrain.AddComponent( + GetElectricMachine(PowertrainPosition.BatteryElectricB4, runData.ElectricMachinesData, container, es, ctl)); + break; + case PowertrainPosition.BatteryElectricB3: + powertrain.AddComponent(new AxleGear(container, runData.AxleGearData)) + .AddComponent( + GetElectricMachine(PowertrainPosition.BatteryElectricB3, runData.ElectricMachinesData, container, es, ctl)); + break; + case PowertrainPosition.BatteryElectricB2: + throw new VectoException("Battery Electric configuration B2 currently not supported"); + default: throw new ArgumentOutOfRangeException(nameof(pos), pos, null); + } + + return container; + } + + private static IElectricMotor GetElectricMachine(PowertrainPosition pos, + IList<Tuple<PowertrainPosition, ElectricMotorData>> electricMachinesData, VehicleContainer container, + IElectricSystem es, IElectricMotorControl ctl) + { + var motorData = electricMachinesData.FirstOrDefault(x => x.Item1 == pos); + if (motorData == null) { + return null; + } + + container.ModData.AddElectricMotor(pos); + //ctl.AddElectricMotor(pos, motorData.Item2); + var motor = new ElectricMotor(container, motorData.Item2, ctl, pos); + motor.Connect(es); + return motor; + } + + private static GearboxData CreateGearboxData() + { + var ratios = new[] { 14.93, 11.64, 9.02, 7.04, 5.64, 4.4, 3.39, 2.65, 2.05, 1.6, 1.28, 1.0 }; + + return new GearboxData { + Gears = ratios.Select( + (ratio, i) => Tuple.Create( + (uint)i, new GearData { + //MaxTorque = 2300.SI<NewtonMeter>(), + LossMap = + TransmissionLossMapReader.ReadFromFile( + ratio.IsEqual(1) ? GearboxIndirectLoss : GearboxDirectLoss, ratio, + string.Format("Gear {0}", i)), + Ratio = ratio, + //ShiftPolygon = DeclarationData.Gearbox.ComputeEfficiencyShiftPolygon(i,) + })).ToDictionary(k => k.Item1 + 1, v => v.Item2), + ShiftTime = 2.SI<Second>(), + Inertia = 0.SI<KilogramSquareMeter>(), + TractionInterruption = 1.SI<Second>(), + TorqueReserve = 0.2, + StartTorqueReserve = 0.2, + DownshiftAfterUpshiftDelay = DeclarationData.Gearbox.DownshiftAfterUpshiftDelay, + UpshiftAfterDownshiftDelay = DeclarationData.Gearbox.UpshiftAfterDownshiftDelay, + UpshiftMinAcceleration = DeclarationData.Gearbox.UpshiftMinAcceleration, + StartSpeed = 2.SI<MeterPerSecond>(), + StartAcceleration = 0.6.SI<MeterPerSquareSecond>(), + }; + } + + private static AxleGearData CreateAxleGearData() + { + var ratio = 2.59; + return new AxleGearData { + AxleGear = new GearData { + Ratio = ratio, + LossMap = TransmissionLossMapReader.Create(0.95, ratio, "Axlegear"), + } + }; + } + + private static VehicleData CreateVehicleData(Kilogram loading) + { + var axles = new List<Axle> { + new Axle { + AxleWeightShare = 0.38, + Inertia = 20.SI<KilogramSquareMeter>(), + RollResistanceCoefficient = 0.007, + TwinTyres = false, + TyreTestLoad = 30436.0.SI<Newton>() + }, + new Axle { + AxleWeightShare = 0.62, + Inertia = 18.SI<KilogramSquareMeter>(), + RollResistanceCoefficient = 0.007, + TwinTyres = true, + TyreTestLoad = 30436.SI<Newton>() + }, + }; + return new VehicleData { + AirDensity = DeclarationData.AirDensity, + AxleConfiguration = AxleConfiguration.AxleConfig_4x2, + CurbMass = 11500.SI<Kilogram>(), + Loading = loading, + DynamicTyreRadius = 0.465.SI<Meter>(), + AxleData = axles, + SavedInDeclarationMode = false + }; + } + + private static AirdragData CreateAirdragData() + { + return new AirdragData() { + CrossWindCorrectionCurve = + new CrosswindCorrectionCdxALookup( + 3.2634.SI<SquareMeter>(), + CrossWindCorrectionCurveReader.GetNoCorrectionCurve(3.2634.SI<SquareMeter>()), + CrossWindCorrectionMode.NoCorrection), + }; + } + + private static DriverData CreateDriverData(string accelerationFile, bool overspeed = false) + { + return new DriverData { + AccelerationCurve = AccelerationCurveReader.ReadFromFile(accelerationFile), + LookAheadCoasting = new DriverData.LACData { + Enabled = true, + MinSpeed = 50.KMPHtoMeterPerSecond(), + + //Deceleration = -0.5.SI<MeterPerSquareSecond>() + LookAheadDistanceFactor = DeclarationData.Driver.LookAhead.LookAheadDistanceFactor, + LookAheadDecisionFactor = new LACDecisionFactor() + }, + OverSpeed = new DriverData.OverSpeedData() { + Enabled = true, + MinSpeed = 50.KMPHtoMeterPerSecond(), + OverSpeed = 5.KMPHtoMeterPerSecond() + }, + EngineStopStart = new DriverData.EngineStopStartData() { + EngineOffStandStillActivationDelay = DeclarationData.Driver.EngineStopStart.ActivationDelay, + MaxEngineOffTimespan = DeclarationData.Driver.EngineStopStart.MaxEngineOffTimespan, + UtilityFactor = DeclarationData.Driver.EngineStopStart.UtilityFactor + } + }; + } + + public static ShiftStrategyParameters CreateGearshiftData(GearboxData gbx, double axleRatio, PerSecond engineIdlingSpeed) + { + var retVal = new ShiftStrategyParameters { + StartVelocity = DeclarationData.GearboxTCU.StartSpeed, + StartAcceleration = DeclarationData.GearboxTCU.StartAcceleration, + GearResidenceTime = DeclarationData.GearboxTCU.GearResidenceTime, + DnT99L_highMin1 = DeclarationData.GearboxTCU.DnT99L_highMin1, + DnT99L_highMin2 = DeclarationData.GearboxTCU.DnT99L_highMin2, + AllowedGearRangeUp = DeclarationData.GearboxTCU.AllowedGearRangeUp, + AllowedGearRangeDown = DeclarationData.GearboxTCU.AllowedGearRangeDown, + LookBackInterval = DeclarationData.GearboxTCU.LookBackInterval, + DriverAccelerationLookBackInterval = DeclarationData.GearboxTCU.DriverAccelerationLookBackInterval, + DriverAccelerationThresholdLow = DeclarationData.GearboxTCU.DriverAccelerationThresholdLow, + AverageCardanPowerThresholdPropulsion = DeclarationData.GearboxTCU.AverageCardanPowerThresholdPropulsion, + CurrentCardanPowerThresholdPropulsion = DeclarationData.GearboxTCU.CurrentCardanPowerThresholdPropulsion, + TargetSpeedDeviationFactor = DeclarationData.GearboxTCU.TargetSpeedDeviationFactor, + EngineSpeedHighDriveOffFactor = DeclarationData.GearboxTCU.EngineSpeedHighDriveOffFactor, + RatingFactorCurrentGear = gbx.Type.AutomaticTransmission() + ? DeclarationData.GearboxTCU.RatingFactorCurrentGearAT + : DeclarationData.GearboxTCU.RatingFactorCurrentGear, + + //-------------------- + RatioEarlyUpshiftFC = DeclarationData.GearboxTCU.RatioEarlyUpshiftFC / axleRatio, + RatioEarlyDownshiftFC = DeclarationData.GearboxTCU.RatioEarlyDownshiftFC / axleRatio, + AllowedGearRangeFC = gbx.Type.AutomaticTransmission() + ? (gbx.Gears.Count > DeclarationData.GearboxTCU.ATSkipGearsThreshold + ? DeclarationData.GearboxTCU.AllowedGearRangeFCATSkipGear + : DeclarationData.GearboxTCU.AllowedGearRangeFCAT) + : DeclarationData.GearboxTCU.AllowedGearRangeFCAMT, + VelocityDropFactor = DeclarationData.GearboxTCU.VelocityDropFactor, + AccelerationFactor = DeclarationData.GearboxTCU.AccelerationFactor, + MinEngineSpeedPostUpshift = 0.RPMtoRad(), + ATLookAheadTime = DeclarationData.GearboxTCU.ATLookAheadTime, + + LoadStageThresoldsUp = DeclarationData.GearboxTCU.LoadStageThresholdsUp, + LoadStageThresoldsDown = DeclarationData.GearboxTCU.LoadStageThresoldsDown, + ShiftSpeedsTCToLocked = DeclarationData.GearboxTCU.ShiftSpeedsTCToLocked + .Select(x => x.Select(y => y + engineIdlingSpeed.AsRPM).ToArray()).ToArray(), + }; + + return retVal; + } + } +} diff --git a/VectoCore/VectoCoreTest/Integration/Hybrid/ParallelHybridTest.cs b/VectoCore/VectoCoreTest/Integration/Hybrid/ParallelHybridTest.cs index e3309ee421bdcac3ab3050e640d1d6d4b02f6af8..67937b3aa66f77fed5e81ecc0ce8dbc1ac029e40 100644 --- a/VectoCore/VectoCoreTest/Integration/Hybrid/ParallelHybridTest.cs +++ b/VectoCore/VectoCoreTest/Integration/Hybrid/ParallelHybridTest.cs @@ -756,26 +756,7 @@ namespace TUGraz.VectoCore.Tests.Integration.Hybrid RatingFactorCurrentGear = gbx.Type.AutomaticTransmission() ? DeclarationData.GearboxTCU.RatingFactorCurrentGearAT : DeclarationData.GearboxTCU.RatingFactorCurrentGear, - //AccelerationReserveLookup = AccelerationReserveLookupReader.ReadFromStream( - // RessourceHelper.ReadStream( - // DeclarationData.DeclarationDataResourcePrefix + ".GearshiftParameters.AccelerationReserveLookup.csv")), - //ShareTorque99L = ShareTorque99lLookupReader.ReadFromStream( - // RessourceHelper.ReadStream( - // DeclarationData.DeclarationDataResourcePrefix + ".GearshiftParameters.ShareTq99L.csv") - //), - //PredictionDurationLookup = PredictionDurationLookupReader.ReadFromStream( - // RessourceHelper.ReadStream( - // DeclarationData.DeclarationDataResourcePrefix + ".GearshiftParameters.PredictionTimeLookup.csv") - //), - //ShareIdleLow = ShareIdleLowReader.ReadFromStream( - // RessourceHelper.ReadStream( - // DeclarationData.DeclarationDataResourcePrefix + ".GearshiftParameters.ShareIdleLow.csv") - //), - //ShareEngineHigh = EngineSpeedHighLookupReader.ReadFromStream( - // RessourceHelper.ReadStream( - // DeclarationData.DeclarationDataResourcePrefix + ".GearshiftParameters.ShareEngineSpeedHigh.csv") - //), - + //-------------------- RatioEarlyUpshiftFC = DeclarationData.GearboxTCU.RatioEarlyUpshiftFC / axleRatio, RatioEarlyDownshiftFC = DeclarationData.GearboxTCU.RatioEarlyDownshiftFC / axleRatio, diff --git a/VectoCore/VectoCoreTest/VectoCoreTest.csproj b/VectoCore/VectoCoreTest/VectoCoreTest.csproj index dfb4f18b540502ae45c83c5d5f6bd75d8401c711..1b94f1b0917d1a6093994a86f21911294491b662 100644 --- a/VectoCore/VectoCoreTest/VectoCoreTest.csproj +++ b/VectoCore/VectoCoreTest/VectoCoreTest.csproj @@ -100,6 +100,7 @@ <Compile Include="GraphProgram.cs" /> <Compile Include="Integration\ADAS\ADASTests.cs" /> <Compile Include="Integration\ATPowerTrain.cs" /> + <Compile Include="Integration\BatteryElectric\BatteryElectricTest.cs" /> <Compile Include="Integration\BusAuxiliaries\AuxDemandTest.cs" /> <Compile Include="Integration\BusAuxiliaries\BusAdapterTest.cs" /> <Compile Include="Integration\BusAuxiliaries\AAuxTests.cs" />