diff --git a/VectoCommon/VectoCommon/Models/IResponse.cs b/VectoCommon/VectoCommon/Models/IResponse.cs index 15984e37ff64f469a95d3031c59a3b431becf25d..497c6a51490be0aead411f18403c7ab63ff5c0c0 100644 --- a/VectoCommon/VectoCommon/Models/IResponse.cs +++ b/VectoCommon/VectoCommon/Models/IResponse.cs @@ -165,6 +165,8 @@ namespace TUGraz.VectoCommon.Models public NewtonMeter TorqueRequest { get; set; } public NewtonMeter InertiaTorque { get; set; } public PerSecond AvgDrivetrainSpeed { get; set; } + public NewtonMeter MaxDriveTorqueEM { get; set; } + public NewtonMeter TorqueRequestEmMap { get; set; } } diff --git a/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs b/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs index e8287a62cd6faa9417d403e2e07b79934affe74d..ee8c57bc534387a3cfab468e9645eb896ebd0d7f 100644 --- a/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs +++ b/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs @@ -601,9 +601,9 @@ namespace TUGraz.VectoCore.Models.Declaration switch (type) { case GearboxType.AMT: - // TODO MQ: 2020-10-14: compute for AMT with ICE and AMT with EM differently - //return ComputeEfficiencyShiftPolygon(gearIdx, fullLoadCurve, gears, engine, axlegearRatio, dynamicTyreRadius); - case GearboxType.MT: + // TODO MQ: 2020-10-14: compute for AMT with ICE and AMT with EM differently + return ComputeEfficiencyShiftPolygon(gearIdx, fullLoadCurve, gears, engine, axlegearRatio, dynamicTyreRadius); + case GearboxType.MT: return ComputeManualTransmissionShiftPolygon( gearIdx, fullLoadCurve, gears, engine, axlegearRatio, dynamicTyreRadius); case GearboxType.ATSerial: @@ -631,19 +631,117 @@ namespace TUGraz.VectoCore.Models.Declaration var downShift = new List<ShiftPolygon.ShiftPolygonEntry>(); var upShift = new List<ShiftPolygon.ShiftPolygonEntry>(); if (gearIdx > 0) { - downShift.Add(new ShiftPolygon.ShiftPolygonEntry(fullLoadCurve.MaxGenerationTorque * emRatio * 1.1, 0.RPMtoRad())); - downShift.Add(new ShiftPolygon.ShiftPolygonEntry(fullLoadCurve.MaxDriveTorque * emRatio * 1.1, 0.RPMtoRad())); + var nMax = fullLoadCurve.NP80low; + var nMin = 0.1 * fullLoadCurve.RatedSpeed; + + downShift.AddRange(DownshiftLineDrive(fullLoadCurve, nMin, nMax)); + downShift.AddRange(DownshiftLineDrag(fullLoadCurve, nMin, nMax)); } if (gearIdx >= gears.Count - 1) { return new ShiftPolygon(downShift, upShift); } - upShift.Add(new ShiftPolygon.ShiftPolygonEntry(fullLoadCurve.MaxGenerationTorque * emRatio * 1.1, fullLoadCurve.MaxSpeed / emRatio * 0.9)); - upShift.Add(new ShiftPolygon.ShiftPolygonEntry(fullLoadCurve.MaxDriveTorque * emRatio * 1.1, fullLoadCurve.MaxSpeed / emRatio * 0.9)); + upShift.Add(new ShiftPolygon.ShiftPolygonEntry(fullLoadCurve.MaxGenerationTorque * 1.1, fullLoadCurve.MaxSpeed * 0.9)); + upShift.Add(new ShiftPolygon.ShiftPolygonEntry(fullLoadCurve.MaxDriveTorque * 1.1, fullLoadCurve.MaxSpeed * 0.9)); return new ShiftPolygon(downShift, upShift); } + private static List<ShiftPolygon.ShiftPolygonEntry> DownshiftLineDrive(ElectricMotorFullLoadCurve fullLoadCurve, PerSecond nMin, PerSecond nMax) + { + var retVal = new List<ShiftPolygon.ShiftPolygonEntry>(); + var downShiftPoints = fullLoadCurve + .FullLoadEntries.Where(fldEntry => fldEntry.MotorSpeed >= nMin && fldEntry.MotorSpeed <= nMax) + .Select( + fldEntry => + new Point(fldEntry.MotorSpeed.Value(), fldEntry.FullDriveTorque.Value() * ShiftPolygonEngineFldMargin)) + .ToList(); + //retVal.Add(new ShiftPolygon.ShiftPolygonEntry(fullLoadCurve.MaxDriveTorque * 1.1, nMax)); + if (downShiftPoints.Count == 0) { + // coarse grid points in FLD + retVal.Add( + new ShiftPolygon.ShiftPolygonEntry( + fullLoadCurve.MaxDriveTorque * 1.1, + nMax)); + retVal.Add( + new ShiftPolygon.ShiftPolygonEntry( + fullLoadCurve.FullLoadDriveTorque(nMax) * ShiftPolygonEngineFldMargin, + nMax)); + retVal.Add( + new ShiftPolygon.ShiftPolygonEntry( + fullLoadCurve.FullLoadDriveTorque(nMin) * ShiftPolygonEngineFldMargin, + nMin)); + + } else { + if (downShiftPoints.Min(x => x.X) > nMin) { + retVal.Add( + new ShiftPolygon.ShiftPolygonEntry( + fullLoadCurve.FullLoadDriveTorque(nMin) * 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) { + retVal.Add( + new ShiftPolygon.ShiftPolygonEntry( + fullLoadCurve.FullLoadDriveTorque(nMax) * ShiftPolygonEngineFldMargin, + nMax)); + } + } + + return retVal; + } + + private static List<ShiftPolygon.ShiftPolygonEntry> DownshiftLineDrag(ElectricMotorFullLoadCurve fullLoadCurve, PerSecond nMin, PerSecond nMax) + { + var retVal = new List<ShiftPolygon.ShiftPolygonEntry>(); + var downShiftPoints = fullLoadCurve + .FullLoadEntries.Where(fldEntry => fldEntry.MotorSpeed >= nMin && fldEntry.MotorSpeed <= nMax) + .Select( + fldEntry => + new Point(fldEntry.MotorSpeed.Value(), fldEntry.FullGenerationTorque.Value() * ShiftPolygonEngineFldMargin)) + .ToList(); + //retVal.Add(new ShiftPolygon.ShiftPolygonEntry(fullLoadCurve.MaxGenerationTorque * 1.1, nMax)); + if (downShiftPoints.Count == 0) { + // coarse grid points in FLD + retVal.Add( + new ShiftPolygon.ShiftPolygonEntry( + fullLoadCurve.FullGenerationTorque(nMin) * ShiftPolygonEngineFldMargin, + nMin)); + retVal.Add( + new ShiftPolygon.ShiftPolygonEntry( + fullLoadCurve.FullGenerationTorque(nMax) * ShiftPolygonEngineFldMargin, + nMax)); + retVal.Add( + new ShiftPolygon.ShiftPolygonEntry( + fullLoadCurve.MaxGenerationTorque * 1.1, + nMax)); + } else { + if (downShiftPoints.Min(x => x.X) > nMin) { + retVal.Add( + new ShiftPolygon.ShiftPolygonEntry( + fullLoadCurve.FullGenerationTorque(nMin) * 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) { + retVal.Add( + new ShiftPolygon.ShiftPolygonEntry( + fullLoadCurve.FullGenerationTorque(nMax) * ShiftPolygonEngineFldMargin, + nMax)); + } + } + + return retVal; + } + public static ShiftPolygon ComputeEfficiencyShiftPolygon( int gearIdx, EngineFullLoadCurve fullLoadCurve, IList<ITransmissionInputData> gears, CombustionEngineData engine, double axlegearRatio, Meter dynamicTyreRadius) diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Data/ElectricMotor/ElectricMotorFullLoadCurve.cs b/VectoCore/VectoCore/Models/SimulationComponent/Data/ElectricMotor/ElectricMotorFullLoadCurve.cs index 224df5bf5d0723336826adaf408bdb5a6ca1ba7c..930d5e84b8414cd199321a641ccfbf5f8f62f611 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Data/ElectricMotor/ElectricMotorFullLoadCurve.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Data/ElectricMotor/ElectricMotorFullLoadCurve.cs @@ -1,16 +1,22 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Diagnostics; using System.Linq; using TUGraz.VectoCommon.Exceptions; +using TUGraz.VectoCommon.Models; using TUGraz.VectoCommon.Utils; +using TUGraz.VectoCore.Models.SimulationComponent.Data.Engine; namespace TUGraz.VectoCore.Models.SimulationComponent.Data.ElectricMotor { - public class ElectricMotorFullLoadCurve + public class ElectricMotorFullLoadCurve : SimulationComponentData { internal readonly List<FullLoadEntry> FullLoadEntries; private NewtonMeter _maxDriveTorque; private NewtonMeter _maxGenerationTorque; private PerSecond _maxSpeed; + private PerSecond _nP80Low; + private Watt _maxPower; + private PerSecond _ratedSpeed; internal ElectricMotorFullLoadCurve(List<FullLoadEntry> entries) @@ -91,6 +97,123 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.ElectricMotor { get { return FullLoadEntries.Select(x => $"{x.MotorSpeed.AsRPM} {x.FullDriveTorque} {x.FullGenerationTorque}").ToArray(); } } + public PerSecond NP80low => _nP80Low ?? (_nP80Low = ComputeNP80LowSpeed()); + public Watt MaxPower => _maxPower ?? (_maxPower = ComputeMaxPower().Item2); + + public PerSecond RatedSpeed => _ratedSpeed ?? (_ratedSpeed = ComputeMaxPower().Item1); + + private Tuple<PerSecond, Watt> ComputeMaxPower() + { + 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]); + if (currentMax.Item2 > max.Item2) { + max = currentMax; + } + } + + return max; + } + + private Tuple<PerSecond, Watt> FindMaxPower(FullLoadEntry p1, FullLoadEntry p2) + { + if (p1.MotorSpeed.IsEqual(p2.MotorSpeed)) { + return Tuple.Create(p1.MotorSpeed, p1.FullDriveTorque * p1.MotorSpeed); + } + + if (p2.MotorSpeed < p1.MotorSpeed) { + var tmp = p1; + p1 = p2; + p2 = tmp; + } + + // y = kx + d + var k = (-p2.FullDriveTorque + p1.FullDriveTorque) / (p2.MotorSpeed - p1.MotorSpeed); + var d = -p2.FullDriveTorque - k * p2.MotorSpeed; + if (k.IsEqual(0)) { + return Tuple.Create(p2.MotorSpeed, -p2.FullDriveTorque * p2.MotorSpeed); + } + var engineSpeedMaxPower = -d / (2 * k); + if (engineSpeedMaxPower.IsSmaller(p1.MotorSpeed) || engineSpeedMaxPower.IsGreater(p2.MotorSpeed)) { + if (-p2.FullDriveTorque * p2.MotorSpeed > -p1.FullDriveTorque * p1.MotorSpeed) { + return Tuple.Create(p2.MotorSpeed, -p2.FullDriveTorque * p2.MotorSpeed); + } + return Tuple.Create(p1.MotorSpeed, -p1.FullDriveTorque * p1.MotorSpeed); + } + var engineTorqueMaxPower = FullLoadDriveTorque(engineSpeedMaxPower); + return Tuple.Create(engineSpeedMaxPower, -engineTorqueMaxPower * engineSpeedMaxPower); + } + + private PerSecond ComputeNP80LowSpeed() + { + var retVal = FindEngineSpeedForPower(0.8 * MaxPower).First(); + return retVal; + } + + private List<PerSecond> FindEngineSpeedForPower(Watt power) + { + var retVal = new List<PerSecond>(); + for (var idx = 1; idx < FullLoadEntries.Count; idx++) { + var solutions = FindEngineSpeedForPower(FullLoadEntries[idx - 1], FullLoadEntries[idx], power); + retVal.AddRange(solutions); + } + retVal.Sort(); + return retVal.Distinct(new SI.EqualityComparer<PerSecond>()).ToList(); + } + + private IEnumerable<PerSecond> FindEngineSpeedForPower(FullLoadEntry p1, FullLoadEntry p2, Watt power) + { + var k = (-p2.FullDriveTorque + p1.FullDriveTorque) / (p2.MotorSpeed - p1.MotorSpeed); + var d = -p2.FullDriveTorque - k * p2.MotorSpeed; + + if (k.IsEqual(0, 0.0001)) { + // constant torque: solve linear equation + // power = M * n_eng_avg + if (d.IsEqual(0, 0.0001)) { + return new List<PerSecond>(); + } + return FilterSolutions((power / d).ToEnumerable(), p1, p2); + } + + // non-constant torque: solve quadratic equation for engine speed (n_eng_avg) + // power = M(n_eng_avg) * n_eng_avg = (k * n_eng_avg + d) * n_eng_avg = k * n_eng_avg^2 + d * n_eng_avg + var retVal = VectoMath.QuadraticEquationSolver(k.Value(), d.Value(), -power.Value()); + if (retVal.Length == 0) { + Log.Info("No real solution found for requested power demand: P: {0}, p1: {1}, p2: {2}", power, p1, p2); + } + return FilterSolutions(retVal.Select(x => Math.Round(x, 6).SI<PerSecond>()), p1, p2); + } + + private IEnumerable<PerSecond> FilterSolutions(IEnumerable<PerSecond> solutions, FullLoadEntry p1, FullLoadEntry p2) + { + return solutions.Where( + x => x.IsGreaterOrEqual(p1.MotorSpeed.Value()) && x.IsSmallerOrEqual(p2.MotorSpeed.Value())); + } + + protected internal Watt ComputeArea(PerSecond lowEngineSpeed, PerSecond highEngineSpeed) + { + var startSegment = FindIndex(lowEngineSpeed); + var endSegment = FindIndex(highEngineSpeed); + + var area = 0.SI<Watt>(); + if (lowEngineSpeed < FullLoadEntries[startSegment].MotorSpeed) { + // add part of the first segment + area += (FullLoadEntries[startSegment].MotorSpeed - lowEngineSpeed) * + (FullLoadDriveTorque(lowEngineSpeed) + FullLoadEntries[startSegment].FullDriveTorque) / 2.0; + } + for (var i = startSegment + 1; i <= endSegment; i++) { + var speedHigh = FullLoadEntries[i].MotorSpeed; + var torqueHigh = FullLoadEntries[i].FullDriveTorque; + if (highEngineSpeed < FullLoadEntries[i].MotorSpeed) { + // add part of the last segment + speedHigh = highEngineSpeed; + torqueHigh = FullLoadDriveTorque(highEngineSpeed); + } + area += (speedHigh - FullLoadEntries[i - 1].MotorSpeed) * (torqueHigh + FullLoadEntries[i - 1].FullDriveTorque) / + 2.0; + } + return area; + } } } \ 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 564b82d29842b164e803bd9fb948388dcc8031c9..7cb5c059f39ae174e9985880736df1846edb2049 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/ElectricMotor.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/ElectricMotor.cs @@ -339,11 +339,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl } retVal.ElectricMotor.MaxDriveTorque = maxDriveTorqueDt; + retVal.ElectricMotor.MaxDriveTorqueEM = maxDriveTorqueEm; retVal.ElectricMotor.MaxRecuperationTorque = maxRecuperationTorqueDt; retVal.ElectricMotor.AngularVelocity = avgEmSpeed; retVal.ElectricMotor.AvgDrivetrainSpeed = avgDtSpeed; retVal.ElectricMotor.TorqueRequest = outTorque; + retVal.ElectricMotor.TorqueRequestEmMap = emTorqueMap; retVal.ElectricMotor.InertiaTorque = avgDtSpeed.IsEqual(0) ? 0.SI<NewtonMeter>() : inertiaTorqueEm * avgEmSpeed / avgDtSpeed; diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/PEVAMTShiftStrategy.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/PEVAMTShiftStrategy.cs index 15fff78cee5e84e6da58ca8fc11950232b0778f2..fe8a3b6c9a90f89e083f7cae79a48a445e163265 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/PEVAMTShiftStrategy.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/PEVAMTShiftStrategy.cs @@ -433,7 +433,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl NewtonMeter inTorque, PerSecond inAngularVelocity, GearshiftPosition currentGear, IResponse response) { // down shift - if (IsBelowDownShiftCurve(currentGear, inTorque, inAngularVelocity)) { + if (IsBelowDownShiftCurve(currentGear, response.ElectricMotor.TorqueRequestEmMap, response.ElectricMotor.AngularVelocity)) { currentGear = GearList.Predecessor(currentGear); //while (SkipGears && currentGear > 1) { // currentGear--; @@ -557,7 +557,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl private GearshiftPosition InitStartGear(Second absTime, NewtonMeter outTorque, PerSecond outAngularVelocity) { - var emSpeeds = new Dictionary<GearshiftPosition, Tuple<PerSecond, PerSecond>>(); + 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--) { @@ -572,14 +572,18 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl var fullLoadPower = -(response.ElectricMotor.MaxDriveTorque * response.ElectricMotor.AngularVelocity); //.DynamicFullLoadPower; //EnginePowerRequest - response.DeltaFullLoad; - var reserve = 1 - response.ElectricMotor.PowerRequest / fullLoadPower; + 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) { + 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>()); + .Cast<PerSecond>(), (response.ElectricMotor.ElectricMotorPowerMech / response.ElectricSystem.RESSPowerDemand).Value()); } } @@ -592,12 +596,27 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl 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 GearboxModelData.Gears[gear.Gear].ShiftPolygon.IsBelowDownshiftCurve(inTorque, inEngineSpeed); + return IsBelowDownshiftCurve(GearboxModelData.Gears[gear.Gear].ShiftPolygon, inTorque, inEngineSpeed); } protected bool IsAboveDownShiftCurve(GearshiftPosition gear, NewtonMeter inTorque, PerSecond inEngineSpeed) diff --git a/VectoCore/VectoCoreTest/Models/Declaration/ShiftPolygonTest.cs b/VectoCore/VectoCoreTest/Models/Declaration/ShiftPolygonTest.cs index 45bad7552f1271ba7fbf06ad9db49781b3b0e331..1d22ae3e10e77c072249101a6ffba62c57e0f9ce 100644 --- a/VectoCore/VectoCoreTest/Models/Declaration/ShiftPolygonTest.cs +++ b/VectoCore/VectoCoreTest/Models/Declaration/ShiftPolygonTest.cs @@ -864,9 +864,10 @@ namespace TUGraz.VectoCore.Tests.Models.Declaration } - [TestCase(@"E:\QUAM\Workspace\VECTO-Bugreports\BugReportTests\Bugreport Jobs\20190307_VECTO-904_Extrapolation\OM-18173493.xml")] + [TestCase(@"E:\QUAM\Workspace\VECTO-Bugreports\BugReportTests\Bugreport Jobs\20190307_VECTO-904_Extrapolation\OM-18173493.xml")] + //[TestCase(@"E:\QUAM\Workspace\VECTO_DEV_Hybrid\Generic Vehicles\Declaration Mode\Group5_Tractor_4x2\Class5_Tractor_DECL.xml")] [Ignore("Confidential data")] - public void ComputeShiftPolygonXML(string xmlJob) + public void ComputeShiftPolygonXML(string xmlJob) { var inputData = xmlInputReader.CreateDeclaration(xmlJob); var dao = new DeclarationDataAdapterHeavyLorry(); @@ -920,5 +921,43 @@ namespace TUGraz.VectoCore.Tests.Models.Declaration g++; } } + + [TestCase()] + public void ComputePEVShiftLines() + { + 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(); + 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; + + var fullLoadCurve = emData.EfficiencyData.VoltageLevels.First().FullLoadCurve.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>(); + for (var i = 0; i < gearboxData.Gears.Count; i++) { + shiftPolygons.Add(DeclarationData.Gearbox.ComputeElectricMotorShiftPolygon(i, emData.EfficiencyData.VoltageLevels.First().FullLoadCurve, 1.0, gearboxData.Gears, + axlegearRatio, r_dyn)); + fullLoadCurves[(uint)(i + 1)] = new EngineFullLoadCurve(fullLoadCurve, null) { EngineData = engineData}; + } + var imageFile = Path.Combine(Path.GetDirectoryName(pevE2Job), Path.GetFileNameWithoutExtension(pevE2Job) + "_shiftlines.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/Utils/ShiftPolygonDrawer.cs b/VectoCore/VectoCoreTest/Utils/ShiftPolygonDrawer.cs index f0a8b95586e6e36b8b42cdafe0a980db949b4b7c..c4895538f51c960d1550ea1f7d5d1e690a3f3b2e 100644 --- a/VectoCore/VectoCoreTest/Utils/ShiftPolygonDrawer.cs +++ b/VectoCore/VectoCoreTest/Utils/ShiftPolygonDrawer.cs @@ -202,14 +202,14 @@ namespace TUGraz.VectoCore.Tests.Utils PlotDragLoad(engineFld, chartArea, chart, name); - PlotEngineSpeedLine(engineFld, chartArea, chart, "nPref " + name, Color.DeepSkyBlue, - engineFld.PreferredSpeed.Value() / Constants.RPMToRad); + //PlotEngineSpeedLine(engineFld, chartArea, chart, "nPref " + name, Color.DeepSkyBlue, + // engineFld.PreferredSpeed.Value() / Constants.RPMToRad); - PlotEngineSpeedLine(engineFld, chartArea, chart, "n95h " + name, Color.Red, - engineFld.N95hSpeed.Value() / Constants.RPMToRad); + //PlotEngineSpeedLine(engineFld, chartArea, chart, "n95h " + name, Color.Red, + // engineFld.N95hSpeed.Value() / Constants.RPMToRad); - PlotEngineSpeedLine(engineFld, chartArea, chart, "n85kmh " + name, Color.LimeGreen, - speed85kmh.Value() / Constants.RPMToRad); + //PlotEngineSpeedLine(engineFld, chartArea, chart, "n85kmh " + name, Color.LimeGreen, + // speed85kmh.Value() / Constants.RPMToRad); PlotEngineSpeedLine(engineFld, chartArea, chart, "nPmax " + name, Color.Coral, engineFld.RatedSpeed.Value() / Constants.RPMToRad);