diff --git a/VECTO/Input Files/Gearbox.vb b/VECTO/Input Files/Gearbox.vb index 30fe86ad28a41d14a7437077a4bb9a8a61465dd6..4ffe936751a56af3e811c1ee06b4d60799a63f05 100644 --- a/VECTO/Input Files/Gearbox.vb +++ b/VECTO/Input Files/Gearbox.vb @@ -222,8 +222,8 @@ Public Class Gearbox engine = GetDefaultEngine(gearbox.Gears) End Try - axlegearData = doa.CreateAxleGearData(gearbox, False) - gearboxData = doa.CreateGearboxData(gearbox, engine, axlegearData.AxleGear.Ratio, rdyn, vehiclecategory, False) + axlegearData = doa.CreateAxleGearData(gearbox) + gearboxData = doa.CreateGearboxData(gearbox, engine, axlegearData.AxleGear.Ratio, rdyn, vehiclecategory) Else Dim doa As EngineeringDataAdapter = New EngineeringDataAdapter() Try @@ -232,8 +232,8 @@ Public Class Gearbox engine = GetDefaultEngine(gearbox.Gears) End Try - axlegearData = doa.CreateAxleGearData(gearbox, True) - gearboxData = doa.CreateGearboxData(gearbox, engine, axlegearData.AxleGear.Ratio, rdyn, vehiclecategory, True) + axlegearData = doa.CreateAxleGearData(gearbox) + gearboxData = doa.CreateGearboxData(gearbox, engine, axlegearData.AxleGear.Ratio, rdyn, vehiclecategory) End If Dim result As IList(Of ValidationResult) = diff --git a/VECTO/Input Files/Vehicle.vb b/VECTO/Input Files/Vehicle.vb index 8de5d9ad4aac197fc14acff4a4c6e5d313ab30ef..247c2cd0735ca242d61eae7b55922c646052e556 100644 --- a/VECTO/Input Files/Vehicle.vb +++ b/VECTO/Input Files/Vehicle.vb @@ -109,14 +109,14 @@ Public Class Vehicle segment.Missions.First().Loadings.First().Value, segment.MunicipalBodyWeight) airdragData = doa.CreateAirdragData(vehicle, segment.Missions.First(), segment) retarderData = doa.CreateRetarderData(vehicle) - angledriveData = doa.CreateAngledriveData(vehicle, False) + angledriveData = doa.CreateAngledriveData(vehicle) ptoData = doa.CreatePTOTransmissionData(vehicle) Else Dim doa As EngineeringDataAdapter = New EngineeringDataAdapter() vehicleData = doa.CreateVehicleData(vehicle) airdragData = doa.CreateAirdragData(vehicle, vehicle) retarderData = doa.CreateRetarderData(vehicle) - angledriveData = doa.CreateAngledriveData(vehicle, True) + angledriveData = doa.CreateAngledriveData(vehicle) ptoData = doa.CreatePTOTransmissionData(vehicle) End If diff --git a/VectoCore/VectoCore/InputData/Reader/ComponentData/TransmissionLossMapReader.cs b/VectoCore/VectoCore/InputData/Reader/ComponentData/TransmissionLossMapReader.cs index 78735f939277c17912244edf57700a2c39fba9e3..995a76b6702436f8c1e6e2fe38831a5b4bcbb668 100644 --- a/VectoCore/VectoCore/InputData/Reader/ComponentData/TransmissionLossMapReader.cs +++ b/VectoCore/VectoCore/InputData/Reader/ComponentData/TransmissionLossMapReader.cs @@ -29,191 +29,185 @@ * Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology */ -using System; -using System.Collections.Generic; -using System.Data; -using System.Linq; -using TUGraz.VectoCommon.Exceptions; -using TUGraz.VectoCommon.Models; -using TUGraz.VectoCommon.Utils; -using TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox; -using TUGraz.VectoCore.Utils; - -namespace TUGraz.VectoCore.InputData.Reader.ComponentData -{ - public static class TransmissionLossMapReader - { - public static TransmissionLossMap ReadFromFile(string fileName, double gearRatio, string gearName) - { - try { - var data = VectoCSVFile.Read(fileName, true); - return Create(data, gearRatio, gearName); - } catch (Exception ex) { - throw new VectoException("ERROR while reading TransmissionLossMap " + gearName + ": " + ex.Message, ex); - } - } - - /// <summary> - /// Create a TransmissionLoss Map from a DataTable. - /// </summary> - /// <param name="data"></param> - /// <param name="gearRatio"></param> - /// <param name="gearName"></param> - /// <param name="extendLossMap"></param> - /// <returns></returns> - public static TransmissionLossMap Create(DataTable data, double gearRatio, string gearName, bool extendLossMap = false) - { - if (data == null || data.Columns.Count < 3) { - throw new VectoException("TransmissionLossMap Data File for {0} must consist of 3 columns.", gearName); - } - - if (data.Rows.Count < 4) { - throw new VectoException( - "TransmissionLossMap for {0} must consist of at least four lines with numeric values (below file header", gearName); - } - - List<TransmissionLossMap.GearLossMapEntry> entries; - if (HeaderIsValid(data.Columns)) { - entries = CreateFromColumnNames(data); - } else { - LoggingObject.Logger<TransmissionLossMap>().Warn( - "TransmissionLossMap {5}: Header line is not valid. Expected: '{0}, {1}, {2}'. Got: '{4}'. Falling back to column index.", - Fields.InputSpeed, Fields.InputTorque, Fields.TorqeLoss, - string.Join(", ", data.Columns.Cast<DataColumn>().Select(c => c.ColumnName).Reverse()), gearName); - - entries = CreateFromColumIndizes(data); - } - if (!extendLossMap) { - return new TransmissionLossMap(entries, gearRatio, gearName); - } - var orig = ""; - entries.ForEach( - x => - orig += - string.Format("{0},{1},{2}" + Environment.NewLine, x.InputSpeed.AsRPM, x.InputTorque.Value(), x.TorqueLoss.Value())); - entries = ExtendLossMap(entries); - var extended = ""; - entries.ForEach( - x => - extended += - string.Format("{0},{1},{2}" + Environment.NewLine, x.InputSpeed.AsRPM, x.InputTorque.Value(), x.TorqueLoss.Value())); - return new TransmissionLossMap(entries, gearRatio, gearName); - } - - private static List<TransmissionLossMap.GearLossMapEntry> ExtendLossMap( - List<TransmissionLossMap.GearLossMapEntry> entries) - { - var maxRpm = entries.Max(x => x.InputSpeed); - var maxTorque = entries.Max(x => x.InputTorque); - var speedBuckets = new Dictionary<PerSecond, List<TransmissionLossMap.GearLossMapEntry>>() { - { 0.RPMtoRad(), new List<TransmissionLossMap.GearLossMapEntry>() }, - { 600.RPMtoRad(), new List<TransmissionLossMap.GearLossMapEntry>() }, - { 900.RPMtoRad(), new List<TransmissionLossMap.GearLossMapEntry>() }, - { 1200.RPMtoRad(), new List<TransmissionLossMap.GearLossMapEntry>() }, - { 1600.RPMtoRad(), new List<TransmissionLossMap.GearLossMapEntry>() }, - { 2000.RPMtoRad(), new List<TransmissionLossMap.GearLossMapEntry>() } - }; - for (var i = 2500; i < maxRpm.AsRPM; i += 500) { - speedBuckets.Add(i.RPMtoRad(), new List<TransmissionLossMap.GearLossMapEntry>()); - } - speedBuckets.Add(maxRpm, new List<TransmissionLossMap.GearLossMapEntry>()); - var keys = speedBuckets.Keys.ToArray(); - foreach (var entry in entries) { - foreach (var speed in keys) { - if (entry.InputTorque.IsGreaterOrEqual(0) && Math.Abs(speed.AsRPM - entry.InputSpeed.AsRPM) < 150) { - speedBuckets[speed].Add(entry); - } - } - } - var torqueStep = 500.SI<NewtonMeter>(); - foreach (var speedBucket in speedBuckets) { - if (speedBucket.Value.Count < 2) { - continue; - } - double k, d, r; - VectoMath.LeastSquaresFitting(speedBucket.Value, x => x.InputTorque.Value(), x => x.TorqueLoss.Value(), out k, out d, - out r); - - for (var inTq = speedBucket.Value.Max(x => x.InputTorque) + torqueStep; inTq <= 2 * maxTorque; inTq += torqueStep) { - entries.Add(new TransmissionLossMap.GearLossMapEntry(speedBucket.Key, inTq, k * inTq + d.SI<NewtonMeter>())); - entries.Add(new TransmissionLossMap.GearLossMapEntry(speedBucket.Key, -inTq, k * inTq + d.SI<NewtonMeter>())); - } - } - - return entries; - } - - /// <summary> - /// Create a DataTable from an efficiency value. - /// </summary> - /// <param name="efficiency"></param> - /// <param name="gearRatio"></param> - /// <param name="gearName"></param> - /// <returns></returns> - public static TransmissionLossMap Create(double efficiency, double gearRatio, string gearName) - { - if (double.IsNaN(efficiency)) { - throw new VectoException("TransmissionLossMap: Efficiency is not a number."); - } - - if (efficiency <= 0) { - throw new VectoException("TransmissionLossMap: Efficiency for gear {0} must be greater than 0", gearName); - } - if (efficiency > 1) { - throw new VectoException("TransmissionLossMap: Efficiency for gear {1} must not be greater than 1", gearName); - } - var entries = new List<TransmissionLossMap.GearLossMapEntry> { - new TransmissionLossMap.GearLossMapEntry(0.RPMtoRad(), 1e5.SI<NewtonMeter>(), - (1 - efficiency) * 1e5.SI<NewtonMeter>()), - new TransmissionLossMap.GearLossMapEntry(0.RPMtoRad(), -1e5.SI<NewtonMeter>(), - (1 - efficiency) * 1e5.SI<NewtonMeter>()), - new TransmissionLossMap.GearLossMapEntry(0.RPMtoRad(), 0.SI<NewtonMeter>(), 0.SI<NewtonMeter>()), - new TransmissionLossMap.GearLossMapEntry(10000.RPMtoRad(), 0.SI<NewtonMeter>(), 0.SI<NewtonMeter>()), - new TransmissionLossMap.GearLossMapEntry(10000.RPMtoRad(), -1e5.SI<NewtonMeter>(), - (1 - efficiency) * 1e5.SI<NewtonMeter>()), - new TransmissionLossMap.GearLossMapEntry(10000.RPMtoRad(), 1e5.SI<NewtonMeter>(), - (1 - efficiency) * 1e5.SI<NewtonMeter>()), - }; - return new TransmissionLossMap(entries, gearRatio, gearName); - } - - private static bool HeaderIsValid(DataColumnCollection columns) - { - return columns.Contains(Fields.InputSpeed) && - columns.Contains(Fields.InputTorque) && - columns.Contains(Fields.TorqeLoss); - } - - private static List<TransmissionLossMap.GearLossMapEntry> CreateFromColumnNames(DataTable data) - { - return (from DataRow row in data.Rows - select new TransmissionLossMap.GearLossMapEntry( - inputSpeed: row.ParseDouble(Fields.InputSpeed).RPMtoRad(), - inputTorque: row.ParseDouble(Fields.InputTorque).SI<NewtonMeter>(), - torqueLoss: row.ParseDouble(Fields.TorqeLoss).SI<NewtonMeter>())) - .ToList(); - } - - private static List<TransmissionLossMap.GearLossMapEntry> CreateFromColumIndizes(DataTable data) - { - return (from DataRow row in data.Rows - select new TransmissionLossMap.GearLossMapEntry( - inputSpeed: row.ParseDouble(0).RPMtoRad(), - inputTorque: row.ParseDouble(1).SI<NewtonMeter>(), - torqueLoss: row.ParseDouble(2).SI<NewtonMeter>())) - .ToList(); - } - - public static class Fields - { - /// <summary>[rpm]</summary> - public const string InputSpeed = "Input Speed"; - - /// <summary>[Nm]</summary> - public const string InputTorque = "Input Torque"; - - /// <summary>[Nm]</summary> - public const string TorqeLoss = "Torque Loss"; - } - } +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using TUGraz.VectoCommon.Exceptions; +using TUGraz.VectoCommon.Models; +using TUGraz.VectoCommon.Utils; +using TUGraz.VectoCore.Models.Declaration; +using TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox; +using TUGraz.VectoCore.Utils; + +namespace TUGraz.VectoCore.InputData.Reader.ComponentData +{ + public static class TransmissionLossMapReader + { + public static TransmissionLossMap ReadFromFile(string fileName, double gearRatio, string gearName, bool extendLossMap = false) + { + try { + var data = VectoCSVFile.Read(fileName, true); + return Create(data, gearRatio, gearName, extendLossMap); + } catch (Exception ex) { + throw new VectoException("ERROR while reading TransmissionLossMap " + gearName + ": " + ex.Message, ex); + } + } + + /// <summary> + /// Create a TransmissionLoss Map from a DataTable. + /// </summary> + /// <param name="data"></param> + /// <param name="gearRatio"></param> + /// <param name="gearName"></param> + /// <param name="extendLossMap"></param> + /// <returns></returns> + public static TransmissionLossMap Create(DataTable data, double gearRatio, string gearName, bool extendLossMap = false) + { + if (data == null || data.Columns.Count < 3) { + throw new VectoException("TransmissionLossMap Data File for {0} must consist of 3 columns.", gearName); + } + + if (data.Rows.Count < 4) { + throw new VectoException( + "TransmissionLossMap for {0} must consist of at least four lines with numeric values (below file header", gearName); + } + + List<TransmissionLossMap.GearLossMapEntry> entries; + if (HeaderIsValid(data.Columns)) { + entries = CreateFromColumnNames(data); + } else { + LoggingObject.Logger<TransmissionLossMap>().Warn( + "TransmissionLossMap {5}: Header line is not valid. Expected: '{0}, {1}, {2}'. Got: '{4}'. Falling back to column index.", + Fields.InputSpeed, Fields.InputTorque, Fields.TorqeLoss, + string.Join(", ", data.Columns.Cast<DataColumn>().Select(c => c.ColumnName).Reverse()), gearName); + + entries = CreateFromColumIndizes(data); + } + if (!extendLossMap) { + return new TransmissionLossMap(entries, gearRatio, gearName); + } + var orig = ""; + entries.ForEach( + x => + orig += + string.Format("{0},{1},{2}" + Environment.NewLine, x.InputSpeed.AsRPM, x.InputTorque.Value(), x.TorqueLoss.Value())); + entries = ExtendLossMap(entries); + var extended = ""; + entries.ForEach( + x => + extended += + string.Format("{0},{1},{2}" + Environment.NewLine, x.InputSpeed.AsRPM, x.InputTorque.Value(), x.TorqueLoss.Value())); + return new TransmissionLossMap(entries, gearRatio, gearName); + } + + private static List<TransmissionLossMap.GearLossMapEntry> ExtendLossMap( + List<TransmissionLossMap.GearLossMapEntry> entries) + { + var maxTorque = entries.Max(x => x.InputTorque); + + var clusterer = new MeanShiftClustering(); + var cluster = clusterer.FindClusters(entries.Select(x => x.InputSpeed.Value()).ToArray(), 1e-1); + var minDistance = cluster.Pairwise((x, y) => Math.Abs(y - x)).Min(); + + var speedBuckets = new Dictionary<PerSecond, List<TransmissionLossMap.GearLossMapEntry>>(); + foreach (var c in cluster) { + speedBuckets.Add(c.SI<PerSecond>(), new List<TransmissionLossMap.GearLossMapEntry>()); + } + foreach (var entry in entries) { + foreach (var speed in cluster) { + if (entry.InputTorque.IsGreaterOrEqual(0) && Math.Abs(speed - entry.InputSpeed.Value()) < minDistance / 2.0) { + speedBuckets[speed.SI<PerSecond>()].Add(entry); + } + } + } + foreach (var speedBucket in speedBuckets) { + if (speedBucket.Value.Count < 2) { + continue; + } + double k, d, r; + VectoMath.LeastSquaresFitting(speedBucket.Value, x => x.InputTorque.Value(), x => x.TorqueLoss.Value(), out k, out d, + out r); + + var inTq = DeclarationData.LossMapExtrapolationFactor * maxTorque; + entries.Add(new TransmissionLossMap.GearLossMapEntry(speedBucket.Key, inTq, k * inTq + d.SI<NewtonMeter>())); + entries.Add(new TransmissionLossMap.GearLossMapEntry(speedBucket.Key, -inTq, k * inTq + d.SI<NewtonMeter>())); + } + + return entries; + } + + /// <summary> + /// Create a DataTable from an efficiency value. + /// </summary> + /// <param name="efficiency"></param> + /// <param name="gearRatio"></param> + /// <param name="gearName"></param> + /// <returns></returns> + public static TransmissionLossMap Create(double efficiency, double gearRatio, string gearName) + { + if (double.IsNaN(efficiency)) { + throw new VectoException("TransmissionLossMap: Efficiency is not a number."); + } + + if (efficiency <= 0) { + throw new VectoException("TransmissionLossMap: Efficiency for gear {0} must be greater than 0", gearName); + } + if (efficiency > 1) { + throw new VectoException("TransmissionLossMap: Efficiency for gear {1} must not be greater than 1", gearName); + } + var entries = new List<TransmissionLossMap.GearLossMapEntry> { + new TransmissionLossMap.GearLossMapEntry(0.RPMtoRad(), 1e5.SI<NewtonMeter>(), + (1 - efficiency) * 1e5.SI<NewtonMeter>()), + new TransmissionLossMap.GearLossMapEntry(0.RPMtoRad(), -1e5.SI<NewtonMeter>(), + (1 - efficiency) * 1e5.SI<NewtonMeter>()), + new TransmissionLossMap.GearLossMapEntry(0.RPMtoRad(), 0.SI<NewtonMeter>(), 0.SI<NewtonMeter>()), + new TransmissionLossMap.GearLossMapEntry(10000.RPMtoRad(), 0.SI<NewtonMeter>(), 0.SI<NewtonMeter>()), + new TransmissionLossMap.GearLossMapEntry(10000.RPMtoRad(), -1e5.SI<NewtonMeter>(), + (1 - efficiency) * 1e5.SI<NewtonMeter>()), + new TransmissionLossMap.GearLossMapEntry(10000.RPMtoRad(), 1e5.SI<NewtonMeter>(), + (1 - efficiency) * 1e5.SI<NewtonMeter>()), + }; + return new TransmissionLossMap(entries, gearRatio, gearName); + } + + private static bool HeaderIsValid(DataColumnCollection columns) + { + return columns.Contains(Fields.InputSpeed) && + columns.Contains(Fields.InputTorque) && + columns.Contains(Fields.TorqeLoss); + } + + private static List<TransmissionLossMap.GearLossMapEntry> CreateFromColumnNames(DataTable data) + { + return (from DataRow row in data.Rows + select new TransmissionLossMap.GearLossMapEntry( + inputSpeed: row.ParseDouble(Fields.InputSpeed).RPMtoRad(), + inputTorque: row.ParseDouble(Fields.InputTorque).SI<NewtonMeter>(), + torqueLoss: row.ParseDouble(Fields.TorqeLoss).SI<NewtonMeter>())) + .ToList(); + } + + private static List<TransmissionLossMap.GearLossMapEntry> CreateFromColumIndizes(DataTable data) + { + return (from DataRow row in data.Rows + select new TransmissionLossMap.GearLossMapEntry( + inputSpeed: row.ParseDouble(0).RPMtoRad(), + inputTorque: row.ParseDouble(1).SI<NewtonMeter>(), + torqueLoss: row.ParseDouble(2).SI<NewtonMeter>())) + .ToList(); + } + + public static class Fields + { + /// <summary>[rpm]</summary> + public const string InputSpeed = "Input Speed"; + + /// <summary>[Nm]</summary> + public const string InputTorque = "Input Torque"; + + /// <summary>[Nm]</summary> + public const string TorqeLoss = "Torque Loss"; + } + } } \ No newline at end of file diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/AbstractSimulationDataAdapter.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/AbstractSimulationDataAdapter.cs index bcfa174634a757eafed04c3cf15dd0afc59c8071..9d511599269cb046a1076eb4ada17a4b2e91cc4f 100644 --- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/AbstractSimulationDataAdapter.cs +++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/AbstractSimulationDataAdapter.cs @@ -155,11 +155,10 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter }; } - protected TransmissionLossMap CreateGearLossMap(ITransmissionInputData gear, uint i, bool useEfficiencyFallback, - bool extendLossMap) + protected TransmissionLossMap CreateGearLossMap(ITransmissionInputData gear, uint i, bool useEfficiencyFallback) { if (gear.LossMap != null) { - return TransmissionLossMapReader.Create(gear.LossMap, gear.Ratio, string.Format("Gear {0}", i + 1), extendLossMap); + return TransmissionLossMapReader.Create(gear.LossMap, gear.Ratio, string.Format("Gear {0}", i + 1), true); } if (useEfficiencyFallback) { return TransmissionLossMapReader.Create(gear.Efficiency, gear.Ratio, string.Format("Gear {0}", i + 1)); @@ -190,13 +189,7 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter gearData.TorqueConverterShiftPolygon = shiftPolygon; } - public AxleGearData CreateAxleGearData(IAxleGearInputData data, bool useEfficiencyFallback) - { - var retVal = SetCommonAxleGearData(data); - retVal.AxleGear.LossMap = ReadAxleLossMap(data, useEfficiencyFallback); - return retVal; - } - + internal TransmissionLossMap ReadAxleLossMap(IAxleGearInputData data, bool useEfficiencyFallback) { TransmissionLossMap axleLossMap; @@ -206,7 +199,7 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter if (data.LossMap == null) { throw new InvalidFileFormatException("LossMap for Axlegear is missing."); } - axleLossMap = TransmissionLossMapReader.Create(data.LossMap, data.Ratio, "Axlegear"); + axleLossMap = TransmissionLossMapReader.Create(data.LossMap, data.Ratio, "Axlegear", true); } if (axleLossMap == null) { throw new InvalidFileFormatException("LossMap for Axlegear is missing."); @@ -235,7 +228,7 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter /// <param name="data"></param> /// <param name="useEfficiencyFallback">if true, the Efficiency value is used if no LossMap is found.</param> /// <returns></returns> - internal AngledriveData CreateAngledriveData(IAngledriveInputData data, bool useEfficiencyFallback) + internal AngledriveData DoCreateAngledriveData(IAngledriveInputData data, bool useEfficiencyFallback) { try { var type = data.Type; @@ -258,7 +251,7 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter }; try { angledriveData.Angledrive.LossMap = TransmissionLossMapReader.Create(data.LossMap, - data.Ratio, "Angledrive"); + data.Ratio, "Angledrive", true); } catch (VectoException ex) { Log.Info("Angledrive Loss Map not found."); if (useEfficiencyFallback) { diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapter.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapter.cs index 04f843b30a24d57aff0d5fa97fd4e1d511b0b96c..481ce541fe2d2b471e098f47ba7feb0c0faf1c41 100644 --- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapter.cs +++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapter.cs @@ -246,7 +246,7 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter } internal GearboxData CreateGearboxData(IGearboxDeclarationInputData gearbox, CombustionEngineData engine, - double axlegearRatio, Meter dynamicTyreRadius, VehicleCategory vehicleCategory, bool useEfficiencyFallback) + double axlegearRatio, Meter dynamicTyreRadius, VehicleCategory vehicleCategory) { if (!gearbox.SavedInDeclarationMode) { WarnDeclarationMode("GearboxData"); @@ -272,7 +272,7 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter var tcShiftPolygon = DeclarationData.TorqueConverter.ComputeShiftPolygon(engine.FullLoadCurves[0]); for (uint i = 0; i < gearsInput.Count; i++) { var gear = gearsInput[(int)i]; - var lossMap = CreateGearLossMap(gear, i, useEfficiencyFallback, true); + var lossMap = CreateGearLossMap(gear, i, false); var shiftPolygon = DeclarationData.Gearbox.ComputeShiftPolygon(gearbox.Type, (int)i, engine.FullLoadCurves[i + 1], gearsInput, engine, @@ -341,6 +341,19 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter retVal.UpshiftMinAcceleration = DeclarationData.Gearbox.UpshiftMinAcceleration; } + public AxleGearData CreateAxleGearData(IAxleGearInputData data) + { + var retVal = SetCommonAxleGearData(data); + retVal.AxleGear.LossMap = ReadAxleLossMap(data, false); + return retVal; + } + + public AngledriveData CreateAngledriveData(IAngledriveInputData data) + { + return DoCreateAngledriveData(data, false); + } + + public IList<VectoRunData.AuxData> CreateAuxiliaryData(IAuxiliariesDeclarationInputData auxInputData, MissionType mission, VehicleClass hvdClass) { diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/EngineeringDataAdapter.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/EngineeringDataAdapter.cs index 8270857d86c7dfcecf48cc7ddf951ca04d99e8f9..50fa01e7e1c40a73e4b171a97f40f695e7556fa5 100644 --- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/EngineeringDataAdapter.cs +++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/EngineeringDataAdapter.cs @@ -159,7 +159,7 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter } internal GearboxData CreateGearboxData(IGearboxEngineeringInputData gearbox, CombustionEngineData engineData, - double axlegearRatio, Meter dynamicTyreRadius, VehicleCategory vehicleCategory, bool useEfficiencyFallback) + double axlegearRatio, Meter dynamicTyreRadius, VehicleCategory vehicleCategory) { if (gearbox.SavedInDeclarationMode) { WarnEngineeringMode("GearboxData"); @@ -187,7 +187,7 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter } for (uint i = 0; i < gearbox.Gears.Count; i++) { var gear = gearbox.Gears[(int)i]; - var lossMap = CreateGearLossMap(gear, i, useEfficiencyFallback, false); + var lossMap = CreateGearLossMap(gear, i, true); var shiftPolygon = gear.ShiftPolygon != null && gear.ShiftPolygon.SourceType != DataSourceType.Missing ? ShiftPolygonReader.Create(gear.ShiftPolygon) @@ -256,6 +256,18 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter retVal.UpshiftMinAcceleration = gearbox.UpshiftMinAcceleration; } + public AxleGearData CreateAxleGearData(IAxleGearInputData data) + { + var retVal = SetCommonAxleGearData(data); + retVal.AxleGear.LossMap = ReadAxleLossMap(data, true); + return retVal; + } + + public AngledriveData CreateAngledriveData(IAngledriveInputData data) + { + return DoCreateAngledriveData(data, true); + } + public IList<VectoRunData.AuxData> CreateAuxiliaryData(IAuxiliariesEngineeringInputData auxInputData) { var auxList = new List<VectoRunData.AuxData>(auxInputData.Auxiliaries.Count + 1) { diff --git a/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeVectoRunDataFactory.cs b/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeVectoRunDataFactory.cs index 9e4e04a75d05ead2796c41601e887a87e8a5dca2..63fccf5b9fddd9ac18f15478593e82a0b96d5270 100644 --- a/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeVectoRunDataFactory.cs +++ b/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationModeVectoRunDataFactory.cs @@ -112,11 +112,11 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl _engineData = _dao.CreateEngineData(vehicle.EngineInputData, vehicle.EngineIdleSpeed, vehicle.GearboxInputData, vehicle.TorqueLimits, vehicle.TankSystem); - _axlegearData = _dao.CreateAxleGearData(vehicle.AxleGearInputData, false); - _angledriveData = _dao.CreateAngledriveData(vehicle.AngledriveInputData, false); + _axlegearData = _dao.CreateAxleGearData(vehicle.AxleGearInputData); + _angledriveData = _dao.CreateAngledriveData(vehicle.AngledriveInputData); _gearboxData = _dao.CreateGearboxData(vehicle.GearboxInputData, _engineData, _axlegearData.AxleGear.Ratio, - tempVehicle.DynamicTyreRadius, tempVehicle.VehicleCategory, false); + tempVehicle.DynamicTyreRadius, tempVehicle.VehicleCategory); _retarderData = _dao.CreateRetarderData(vehicle.RetarderInputData); _ptoTransmissionData = _dao.CreatePTOTransmissionData(vehicle.PTOTransmissionInputData); diff --git a/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationVTPModeVectoRunDataFactory.cs b/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationVTPModeVectoRunDataFactory.cs index 56344120737e54195d63d71f48ddd5e629525f44..3ec8f03d7e4bb6db7e4a7f30c4c033098f35d1f5 100644 --- a/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationVTPModeVectoRunDataFactory.cs +++ b/VectoCore/VectoCore/InputData/Reader/Impl/DeclarationVTPModeVectoRunDataFactory.cs @@ -129,12 +129,12 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl vehicle.EngineInputData, vehicle.EngineIdleSpeed, vehicle.GearboxInputData, vehicle.TorqueLimits, vehicle.TankSystem); - _axlegearData = _dao.CreateAxleGearData(vehicle.AxleGearInputData, false); - _angledriveData = _dao.CreateAngledriveData(vehicle.AngledriveInputData, false); + _axlegearData = _dao.CreateAxleGearData(vehicle.AxleGearInputData); + _angledriveData = _dao.CreateAngledriveData(vehicle.AngledriveInputData); _gearboxData = _dao.CreateGearboxData( vehicle.GearboxInputData, _engineData, _axlegearData.AxleGear.Ratio, - tempVehicle.DynamicTyreRadius, tempVehicle.VehicleCategory, false); + tempVehicle.DynamicTyreRadius, tempVehicle.VehicleCategory); _retarderData = _dao.CreateRetarderData(vehicle.RetarderInputData); _ptoTransmissionData = diff --git a/VectoCore/VectoCore/InputData/Reader/Impl/EngineeringModeVectoRunDataFactory.cs b/VectoCore/VectoCore/InputData/Reader/Impl/EngineeringModeVectoRunDataFactory.cs index 89c3119ec51bac43bb4572a6906370cb59c9fa2f..f3bf02051f09fc368c12d37d9042c811f9fee462 100644 --- a/VectoCore/VectoCore/InputData/Reader/Impl/EngineeringModeVectoRunDataFactory.cs +++ b/VectoCore/VectoCore/InputData/Reader/Impl/EngineeringModeVectoRunDataFactory.cs @@ -67,12 +67,12 @@ namespace TUGraz.VectoCore.InputData.Reader.Impl var tempVehicle = dao.CreateVehicleData(vehicle); - var axlegearData = dao.CreateAxleGearData(vehicle.AxleGearInputData, useEfficiencyFallback: true); + var axlegearData = dao.CreateAxleGearData(vehicle.AxleGearInputData); var gearboxData = dao.CreateGearboxData(vehicle.GearboxInputData, engineData, axlegearData.AxleGear.Ratio, - tempVehicle.DynamicTyreRadius,tempVehicle.VehicleCategory, useEfficiencyFallback: true); + tempVehicle.DynamicTyreRadius,tempVehicle.VehicleCategory); var crossWindRequired = vehicle.AirdragInputData.CrossWindCorrectionMode == CrossWindCorrectionMode.VAirBetaLookupTable; - var angledriveData = dao.CreateAngledriveData(vehicle.AngledriveInputData, useEfficiencyFallback: true); + var angledriveData = dao.CreateAngledriveData(vehicle.AngledriveInputData); var ptoTransmissionData = dao.CreatePTOTransmissionData(vehicle.PTOTransmissionInputData); return InputDataProvider.JobInputData.Cycles.Select(cycle => { diff --git a/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs b/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs index 7e070105961ed483f079aaee5088bdb446848095..ca405f3098dca94505d35595428e071cd4cd54b4 100644 --- a/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs +++ b/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs @@ -77,6 +77,7 @@ namespace TUGraz.VectoCore.Models.Declaration public static readonly StandardBodies StandardBodies = new StandardBodies(); public static readonly Payloads Payloads = new Payloads(); public static readonly PTOTransmission PTOTransmission = new PTOTransmission(); + public const double LossMapExtrapolationFactor = 3; public static readonly ADASCombinations ADASCombinations = new ADASCombinations(); public static readonly ADASBenefits ADASBenefits = new ADASBenefits(); diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TransmissionLossMap.cs b/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TransmissionLossMap.cs index ea99a0124c754b2f8f185ce7de1c494a771972e5..e6b366e866b03905a8928da880658d7709b5f1c8 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TransmissionLossMap.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/TransmissionLossMap.cs @@ -42,7 +42,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox { public sealed class TransmissionLossMap : LoggingObject { - [ValidateObject] private readonly IReadOnlyList<GearLossMapEntry> _entries; + [ValidateObject] internal readonly IReadOnlyList<GearLossMapEntry> _entries; private readonly double _ratio; @@ -146,7 +146,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox [Required, SIRange(0, 10000 * Constants.RPMToRad)] public PerSecond InputSpeed { get; private set; } - [Required, SIRange(-100000, 100000)] + //[Required, SIRange(-100000, 100000)] public NewtonMeter InputTorque { get; private set; } [Required, SIRange(0, 100000)] diff --git a/VectoCore/VectoCore/Utils/MeanShiftClustering.cs b/VectoCore/VectoCore/Utils/MeanShiftClustering.cs new file mode 100644 index 0000000000000000000000000000000000000000..e0440d6f3013631504c9b790a3b4640d86630e4a --- /dev/null +++ b/VectoCore/VectoCore/Utils/MeanShiftClustering.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using TUGraz.VectoCommon.Utils; + +namespace TUGraz.VectoCore.Utils +{ + public class MeanShiftClustering + { + + public int MaxIterations { get; set; } + + public double UpdateTolerance { get; set; } + + public int ClusterCount { get; set; } + + public MeanShiftClustering() + { + MaxIterations = 20; + UpdateTolerance = 1e-3; + ClusterCount = 50; + } + + public double[] FindClusters(double[] numbers, double clusterTolerance) + { + var min = numbers.Min(); + var max = numbers.Max(); + var clusterDistance = (max - min) / ClusterCount; + var clusters = new Cluster[ClusterCount]; + for (var i = 0; i < ClusterCount; i++) { + clusters[i] = new Cluster(min + (i + 0.5) * clusterDistance); + } + + IterationCount = 0; + var updated = true; + while (IterationCount++ < MaxIterations && updated) { + for (var clusterIdx = 0; clusterIdx < ClusterCount; clusterIdx++) { + var minDist = double.MaxValue; + var minIdx = -1; + for (var valueIdx = 0; valueIdx < numbers.Length; valueIdx++) { + if (clusters[clusterIdx].Distance(numbers[valueIdx]) < minDist) { + minDist = clusters[clusterIdx].Distance(numbers[valueIdx]); + minIdx = valueIdx; + } + } + + if (minIdx >= 0) { + clusters[clusterIdx].AddValue(numbers[minIdx]); + } + } + + updated = false; + for (int i = 0; i < ClusterCount; i++) { + updated |= clusters[i].Update(UpdateTolerance); + } + } + + return clusters.Select(c => c.Center).Distinct(new ClusterComparer(clusterTolerance)).ToArray(); + } + + public int IterationCount { get; protected set; } + + public struct Cluster + { + private int _count; + private double _sum; + + public Cluster(double center) + { + Center = center; + _sum = 0.0; + _count = 0; + } + + public double Center { get; private set; } + + public double Distance(double val) + { + return Math.Abs(Center - val); + } + + public void AddValue(double val) + { + _sum += val; + _count++; + } + + public double? Mean { get { return _count > 0 ? _sum / _count : (double?)null; } } + + public override string ToString() + { + return string.Format("[{0},{2}]", Center, Mean); + } + + public bool Update(double tolerance) + { + if (Mean == null) + return false; + var retVal = Math.Abs(Center - Mean.Value) > tolerance; + Center = Mean.Value; + _count = 0; + _sum = 0; + return retVal; + } + } + } + + public class ClusterComparer : IEqualityComparer<double> + { + protected readonly double Tolerance; + + public ClusterComparer(double updateTolerance) + { + Tolerance = updateTolerance; + } + + #region Implementation of IEqualityComparer<in double> + + public bool Equals(double x, double y) + { + return x.IsEqual(y, Tolerance); + } + + public int GetHashCode(double obj) + { + return 0; + } + + #endregion + } +} diff --git a/VectoCore/VectoCore/VectoCore.csproj b/VectoCore/VectoCore/VectoCore.csproj index ffa6ab0bd9cc33418d725e6f089f9558a384214d..ac90b8ee3794c0cc2013e39121674c72bb274479 100644 --- a/VectoCore/VectoCore/VectoCore.csproj +++ b/VectoCore/VectoCore/VectoCore.csproj @@ -213,6 +213,7 @@ <Compile Include="OutputData\XML\XMLDeclarationWriter.cs" /> <Compile Include="OutputData\XML\XMLEngineeringWriter.cs" /> <Compile Include="OutputData\XML\XMLManufacturerReport.cs" /> + <Compile Include="Utils\MeanShiftClustering.cs" /> <Compile Include="Utils\ProviderExtensions.cs" /> <Compile Include="Models\Declaration\AirDrag.cs" /> <Compile Include="Models\Declaration\Fan.cs" /> diff --git a/VectoCore/VectoCoreTest/Utils/DelauneyMapTest.cs b/VectoCore/VectoCoreTest/Algorithms/DelaunayMapTest.cs similarity index 96% rename from VectoCore/VectoCoreTest/Utils/DelauneyMapTest.cs rename to VectoCore/VectoCoreTest/Algorithms/DelaunayMapTest.cs index 690297e5c6be0862a0229b0c66a4dcbb25fce08d..7367f32c023455a154ffbd63c2a5d63a9a460473 100644 --- a/VectoCore/VectoCoreTest/Utils/DelauneyMapTest.cs +++ b/VectoCore/VectoCoreTest/Algorithms/DelaunayMapTest.cs @@ -1,213 +1,221 @@ -/* -* This file is part of VECTO. -* -* Copyright © 2012-2017 European Union -* -* Developed by Graz University of Technology, -* Institute of Internal Combustion Engines and Thermodynamics, -* Institute of Technical Informatics -* -* VECTO is licensed under the EUPL, Version 1.1 or - as soon they will be approved -* by the European Commission - subsequent versions of the EUPL (the "Licence"); -* You may not use VECTO except in compliance with the Licence. -* You may obtain a copy of the Licence at: -* -* https://joinup.ec.europa.eu/community/eupl/og_page/eupl -* -* Unless required by applicable law or agreed to in writing, VECTO -* distributed under the Licence is distributed on an "AS IS" basis, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the Licence for the specific language governing permissions and -* limitations under the Licence. -* -* Authors: -* Stefan Hausberger, hausberger@ivt.tugraz.at, IVT, Graz University of Technology -* Christian Kreiner, christian.kreiner@tugraz.at, ITI, Graz University of Technology -* Michael Krisper, michael.krisper@tugraz.at, ITI, Graz University of Technology -* Raphael Luz, luz@ivt.tugraz.at, IVT, Graz University of Technology -* Markus Quaritsch, markus.quaritsch@tugraz.at, IVT, Graz University of Technology -* Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology -*/ - -using NUnit.Framework; -using System; -using System.IO; -using System.Linq; -using TUGraz.VectoCommon.Exceptions; -using TUGraz.VectoCommon.Utils; -using TUGraz.VectoCore.Utils; - -namespace TUGraz.VectoCore.Tests.Utils -{ - [TestFixture] - public class DelaunayMapTest - { - [TestCase] - public void Test_Simple_DelaunayMap() - { - var map = new DelaunayMap("TEST"); - map.AddPoint(0, 0, 0); - map.AddPoint(1, 0, 0); - map.AddPoint(0, 1, 0); - - map.Triangulate(); - - var result = map.Interpolate(0.25, 0.25); - - AssertHelper.AreRelativeEqual(0, result); - } - - [TestCase] - public void Test_DelaunayMapTriangle() - { - var map = new DelaunayMap("TEST"); - map.AddPoint(0, 0, 0); - map.AddPoint(1, 0, 1); - map.AddPoint(0, 1, 2); - - map.Triangulate(); - - // fixed points - AssertHelper.AreRelativeEqual(0, map.Interpolate(0, 0)); - AssertHelper.AreRelativeEqual(1, map.Interpolate(1, 0)); - AssertHelper.AreRelativeEqual(2, map.Interpolate(0, 1)); - - // interpolations - AssertHelper.AreRelativeEqual(0.5, map.Interpolate(0.5, 0)); - AssertHelper.AreRelativeEqual(1, map.Interpolate(0, 0.5)); - AssertHelper.AreRelativeEqual(1.5, map.Interpolate(0.5, 0.5)); - - AssertHelper.AreRelativeEqual(0.25, map.Interpolate(0.25, 0)); - AssertHelper.AreRelativeEqual(0.5, map.Interpolate(0, 0.25)); - AssertHelper.AreRelativeEqual(0.75, map.Interpolate(0.25, 0.25)); - - AssertHelper.AreRelativeEqual(0.75, map.Interpolate(0.75, 0)); - AssertHelper.AreRelativeEqual(1.5, map.Interpolate(0, 0.75)); - - // extrapolation (should fail) - Assert.IsNull(map.Interpolate(1, 1)); - Assert.IsNull(map.Interpolate(-1, -1)); - Assert.IsNull(map.Interpolate(1, -1)); - Assert.IsNull(map.Interpolate(-1, 1)); - } - - public void Test_DelaunayMapPlane() - { - var map = new DelaunayMap("TEST"); - map.AddPoint(0, 0, 0); - map.AddPoint(1, 0, 1); - map.AddPoint(0, 1, 2); - map.AddPoint(1, 1, 3); - - map.Triangulate(); - - // fixed points - AssertHelper.AreRelativeEqual(0, map.Interpolate(0, 0)); - AssertHelper.AreRelativeEqual(1, map.Interpolate(1, 0)); - AssertHelper.AreRelativeEqual(2, map.Interpolate(0, 1)); - AssertHelper.AreRelativeEqual(3, map.Interpolate(1, 1)); - - // interpolations - AssertHelper.AreRelativeEqual(0.5, map.Interpolate(0.5, 0)); - AssertHelper.AreRelativeEqual(1, map.Interpolate(0, 0.5)); - AssertHelper.AreRelativeEqual(2, map.Interpolate(1, 0.5)); - AssertHelper.AreRelativeEqual(2.5, map.Interpolate(0.5, 1)); - - AssertHelper.AreRelativeEqual(1.5, map.Interpolate(0.5, 0.5)); - - AssertHelper.AreRelativeEqual(0.75, map.Interpolate(0.25, 0.25)); - AssertHelper.AreRelativeEqual(2.25, map.Interpolate(0.75, 0.75)); - - AssertHelper.AreRelativeEqual(1.75, map.Interpolate(0.25, 0.75)); - AssertHelper.AreRelativeEqual(1.25, map.Interpolate(0.75, 0.25)); - - // extrapolation (should fail) - AssertHelper.Exception<VectoException>(() => map.Interpolate(1.5, 0.5), "Interpolation failed."); - AssertHelper.Exception<VectoException>(() => map.Interpolate(1.5, 1.5), "Interpolation failed."); - AssertHelper.Exception<VectoException>(() => map.Interpolate(0.5, 1.5), "Interpolation failed."); - AssertHelper.Exception<VectoException>(() => map.Interpolate(-0.5, 1.5), "Interpolation failed."); - AssertHelper.Exception<VectoException>(() => map.Interpolate(-0.5, 0.5), "Interpolation failed."); - AssertHelper.Exception<VectoException>(() => map.Interpolate(-1.5, -1.5), "Interpolation failed."); - AssertHelper.Exception<VectoException>(() => map.Interpolate(0.5, -0.5), "Interpolation failed."); - AssertHelper.Exception<VectoException>(() => map.Interpolate(-1.5, -0.5), "Interpolation failed."); - } - - [TestCase] - public void Test_Delaunay_LessThan3Points() - { - AssertHelper.Exception<ArgumentException>(() => new DelaunayMap("TEST").Triangulate(), - "TEST: Triangulation needs at least 3 Points. Got 0 Points."); - - AssertHelper.Exception<ArgumentException>(() => { - var map1 = new DelaunayMap("TEST"); - map1.AddPoint(1, 0, 0); - map1.Triangulate(); - }, "TEST: Triangulation needs at least 3 Points. Got 1 Points."); - - AssertHelper.Exception<ArgumentException>(() => { - var map2 = new DelaunayMap("TEST"); - map2.AddPoint(1, 0, 0); - map2.AddPoint(0, 1, 0); - map2.Triangulate(); - }, "TEST: Triangulation needs at least 3 Points. Got 2 Points."); - - var map = new DelaunayMap("TEST"); - map.AddPoint(1, 0, 0); - map.AddPoint(0, 1, 0); - map.AddPoint(0, 0, 1); - map.Triangulate(); - } - - [TestCase] - public void Test_Delaunay_DuplicatePoints() - { - var map = new DelaunayMap("TEST"); - map.AddPoint(0, 0, 0); - map.AddPoint(1, 0, 1); - map.AddPoint(1, 1, 3); - map.AddPoint(0, 1, 2); - map.AddPoint(1, 1, 5); - - AssertHelper.Exception<VectoException>(() => { map.Triangulate(); }, - "TEST: Input Data for Delaunay map contains duplicates! \n1 / 1"); - } - - [TestCase] - public void Test_Delaunay_NormalOperation() - { - foreach (var factors in new[] { - Tuple.Create(1.0, 1.0), - Tuple.Create(1.0, 0.04), - Tuple.Create(1.0, 0.1), - Tuple.Create(1.0, 0.01), - Tuple.Create(1.0, 0.0001) - }) { - var xfactor = factors.Item1; - var yfactor = factors.Item2; - - var map = new DelaunayMap("TEST"); - var points = - File.ReadAllLines(@"TestData\Components\40t_Long_Haul_Truck.vmap") - .Skip(1) - .Select(s => { - var p = s.Split(',').ToDouble().ToList(); - return new Point(p[0] * xfactor, p[1] * yfactor, p[2]); - }) - .ToList(); - - points.ForEach(p => map.AddPoint(p.X, p.Y, p.Z)); - map.Triangulate(); - - // test fixed points - foreach (var p in points) { - AssertHelper.AreRelativeEqual(p.Z, map.Interpolate(p.X, p.Y)); - } - map.DrawGraph(); - - // test one arbitrary point in the middle - AssertHelper.AreRelativeEqual(37681, map.Interpolate(1500 * xfactor, 1300 * yfactor), - string.Format("{0}, {1}", xfactor, yfactor)); - } - } - } +/* +* This file is part of VECTO. +* +* Copyright © 2012-2017 European Union +* +* Developed by Graz University of Technology, +* Institute of Internal Combustion Engines and Thermodynamics, +* Institute of Technical Informatics +* +* VECTO is licensed under the EUPL, Version 1.1 or - as soon they will be approved +* by the European Commission - subsequent versions of the EUPL (the "Licence"); +* You may not use VECTO except in compliance with the Licence. +* You may obtain a copy of the Licence at: +* +* https://joinup.ec.europa.eu/community/eupl/og_page/eupl +* +* Unless required by applicable law or agreed to in writing, VECTO +* distributed under the Licence is distributed on an "AS IS" basis, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the Licence for the specific language governing permissions and +* limitations under the Licence. +* +* Authors: +* Stefan Hausberger, hausberger@ivt.tugraz.at, IVT, Graz University of Technology +* Christian Kreiner, christian.kreiner@tugraz.at, ITI, Graz University of Technology +* Michael Krisper, michael.krisper@tugraz.at, ITI, Graz University of Technology +* Raphael Luz, luz@ivt.tugraz.at, IVT, Graz University of Technology +* Markus Quaritsch, markus.quaritsch@tugraz.at, IVT, Graz University of Technology +* Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology +*/ + +using System; +using System.IO; +using System.Linq; +using NUnit.Framework; +using TUGraz.VectoCommon.Exceptions; +using TUGraz.VectoCommon.Utils; +using TUGraz.VectoCore.Tests.Utils; +using TUGraz.VectoCore.Utils; + +namespace TUGraz.VectoCore.Tests.Algorithms +{ + [TestFixture] + public class DelaunayMapTest + { + [OneTimeSetUp] + public void RunBeforeAnyTests() + { + Directory.SetCurrentDirectory(TestContext.CurrentContext.TestDirectory); + } + + + [TestCase] + public void Test_Simple_DelaunayMap() + { + var map = new DelaunayMap("TEST"); + map.AddPoint(0, 0, 0); + map.AddPoint(1, 0, 0); + map.AddPoint(0, 1, 0); + + map.Triangulate(); + + var result = map.Interpolate(0.25, 0.25); + + AssertHelper.AreRelativeEqual(0, result); + } + + [TestCase] + public void Test_DelaunayMapTriangle() + { + var map = new DelaunayMap("TEST"); + map.AddPoint(0, 0, 0); + map.AddPoint(1, 0, 1); + map.AddPoint(0, 1, 2); + + map.Triangulate(); + + // fixed points + AssertHelper.AreRelativeEqual(0, map.Interpolate(0, 0)); + AssertHelper.AreRelativeEqual(1, map.Interpolate(1, 0)); + AssertHelper.AreRelativeEqual(2, map.Interpolate(0, 1)); + + // interpolations + AssertHelper.AreRelativeEqual(0.5, map.Interpolate(0.5, 0)); + AssertHelper.AreRelativeEqual(1, map.Interpolate(0, 0.5)); + AssertHelper.AreRelativeEqual(1.5, map.Interpolate(0.5, 0.5)); + + AssertHelper.AreRelativeEqual(0.25, map.Interpolate(0.25, 0)); + AssertHelper.AreRelativeEqual(0.5, map.Interpolate(0, 0.25)); + AssertHelper.AreRelativeEqual(0.75, map.Interpolate(0.25, 0.25)); + + AssertHelper.AreRelativeEqual(0.75, map.Interpolate(0.75, 0)); + AssertHelper.AreRelativeEqual(1.5, map.Interpolate(0, 0.75)); + + // extrapolation (should fail) + Assert.IsNull(map.Interpolate(1, 1)); + Assert.IsNull(map.Interpolate(-1, -1)); + Assert.IsNull(map.Interpolate(1, -1)); + Assert.IsNull(map.Interpolate(-1, 1)); + } + + public void Test_DelaunayMapPlane() + { + var map = new DelaunayMap("TEST"); + map.AddPoint(0, 0, 0); + map.AddPoint(1, 0, 1); + map.AddPoint(0, 1, 2); + map.AddPoint(1, 1, 3); + + map.Triangulate(); + + // fixed points + AssertHelper.AreRelativeEqual(0, map.Interpolate(0, 0)); + AssertHelper.AreRelativeEqual(1, map.Interpolate(1, 0)); + AssertHelper.AreRelativeEqual(2, map.Interpolate(0, 1)); + AssertHelper.AreRelativeEqual(3, map.Interpolate(1, 1)); + + // interpolations + AssertHelper.AreRelativeEqual(0.5, map.Interpolate(0.5, 0)); + AssertHelper.AreRelativeEqual(1, map.Interpolate(0, 0.5)); + AssertHelper.AreRelativeEqual(2, map.Interpolate(1, 0.5)); + AssertHelper.AreRelativeEqual(2.5, map.Interpolate(0.5, 1)); + + AssertHelper.AreRelativeEqual(1.5, map.Interpolate(0.5, 0.5)); + + AssertHelper.AreRelativeEqual(0.75, map.Interpolate(0.25, 0.25)); + AssertHelper.AreRelativeEqual(2.25, map.Interpolate(0.75, 0.75)); + + AssertHelper.AreRelativeEqual(1.75, map.Interpolate(0.25, 0.75)); + AssertHelper.AreRelativeEqual(1.25, map.Interpolate(0.75, 0.25)); + + // extrapolation (should fail) + AssertHelper.Exception<VectoException>(() => map.Interpolate(1.5, 0.5), "Interpolation failed."); + AssertHelper.Exception<VectoException>(() => map.Interpolate(1.5, 1.5), "Interpolation failed."); + AssertHelper.Exception<VectoException>(() => map.Interpolate(0.5, 1.5), "Interpolation failed."); + AssertHelper.Exception<VectoException>(() => map.Interpolate(-0.5, 1.5), "Interpolation failed."); + AssertHelper.Exception<VectoException>(() => map.Interpolate(-0.5, 0.5), "Interpolation failed."); + AssertHelper.Exception<VectoException>(() => map.Interpolate(-1.5, -1.5), "Interpolation failed."); + AssertHelper.Exception<VectoException>(() => map.Interpolate(0.5, -0.5), "Interpolation failed."); + AssertHelper.Exception<VectoException>(() => map.Interpolate(-1.5, -0.5), "Interpolation failed."); + } + + [TestCase] + public void Test_Delaunay_LessThan3Points() + { + AssertHelper.Exception<ArgumentException>(() => new DelaunayMap("TEST").Triangulate(), + "TEST: Triangulation needs at least 3 Points. Got 0 Points."); + + AssertHelper.Exception<ArgumentException>(() => { + var map1 = new DelaunayMap("TEST"); + map1.AddPoint(1, 0, 0); + map1.Triangulate(); + }, "TEST: Triangulation needs at least 3 Points. Got 1 Points."); + + AssertHelper.Exception<ArgumentException>(() => { + var map2 = new DelaunayMap("TEST"); + map2.AddPoint(1, 0, 0); + map2.AddPoint(0, 1, 0); + map2.Triangulate(); + }, "TEST: Triangulation needs at least 3 Points. Got 2 Points."); + + var map = new DelaunayMap("TEST"); + map.AddPoint(1, 0, 0); + map.AddPoint(0, 1, 0); + map.AddPoint(0, 0, 1); + map.Triangulate(); + } + + [TestCase] + public void Test_Delaunay_DuplicatePoints() + { + var map = new DelaunayMap("TEST"); + map.AddPoint(0, 0, 0); + map.AddPoint(1, 0, 1); + map.AddPoint(1, 1, 3); + map.AddPoint(0, 1, 2); + map.AddPoint(1, 1, 5); + + AssertHelper.Exception<VectoException>(() => { map.Triangulate(); }, + "TEST: Input Data for Delaunay map contains duplicates! \n1 / 1"); + } + + [TestCase] + public void Test_Delaunay_NormalOperation() + { + foreach (var factors in new[] { + Tuple.Create(1.0, 1.0), + Tuple.Create(1.0, 0.04), + Tuple.Create(1.0, 0.1), + Tuple.Create(1.0, 0.01), + Tuple.Create(1.0, 0.0001) + }) { + var xfactor = factors.Item1; + var yfactor = factors.Item2; + + var map = new DelaunayMap("TEST"); + var points = + File.ReadAllLines(@"TestData\Components\40t_Long_Haul_Truck.vmap") + .Skip(1) + .Select(s => { + var p = s.Split(',').ToDouble().ToList(); + return new Point(p[0] * xfactor, p[1] * yfactor, p[2]); + }) + .ToList(); + + points.ForEach(p => map.AddPoint(p.X, p.Y, p.Z)); + map.Triangulate(); + + // test fixed points + foreach (var p in points) { + AssertHelper.AreRelativeEqual(p.Z, map.Interpolate(p.X, p.Y)); + } + map.DrawGraph(); + + // test one arbitrary point in the middle + AssertHelper.AreRelativeEqual(37681, map.Interpolate(1500 * xfactor, 1300 * yfactor), + string.Format("{0}, {1}", xfactor, yfactor)); + } + } + } } \ No newline at end of file diff --git a/VectoCore/VectoCoreTest/Algorithms/MeanShiftClusteringTest.cs b/VectoCore/VectoCoreTest/Algorithms/MeanShiftClusteringTest.cs new file mode 100644 index 0000000000000000000000000000000000000000..7d92c97b01ae0d3d2c7785c2c024312e8f4fbf31 --- /dev/null +++ b/VectoCore/VectoCoreTest/Algorithms/MeanShiftClusteringTest.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using NUnit.Framework.Internal; +using TUGraz.VectoCore.Utils; + +namespace TUGraz.VectoCore.Tests.Algorithms +{ + [TestFixture] + public class MeanShiftClusteringTest + { + + [TestCase] + public void TestClusteringClusters() + { + var centers = new[] { 100.0, 200, 300, 400 }; + var entries = new List<double>(); + var rnd = new Random(centers.Length); + foreach (var center in centers) { + var sum = 0.0; + for (var i = 0; i < 30; i++) { + var val = center + rnd.NextDouble() * 5 - 2.5; + sum += val; + entries.Add(val); + } + //Console.WriteLine(sum / 30); + } + + //Console.WriteLine(string.Join(", ", entries)); + + var clusterer = new MeanShiftClustering() { + ClusterCount = 8 + }; + var clusters = clusterer.FindClusters(entries.ToArray(), 10); + + //Console.WriteLine(clusterer.IterationCount); + Console.WriteLine(string.Join(", ", centers)); + Console.WriteLine(string.Join(", ", clusters)); + + Assert.AreEqual(centers.Length, clusters.Length); + foreach (var center in centers) { + Assert.IsTrue(clusters.Any(x => Math.Abs(center - x) < 2.5)); + } + } + + [TestCase] + public void TestClusteringRandom() + { + var entries = new double[100]; + var rnd = new Random(0); + for (var i = 0; i < entries.Length; i++) { + entries[i] = rnd.NextDouble() * 100; + } + + var clusterer = new MeanShiftClustering(); + var clusters = clusterer.FindClusters(entries.ToArray(), 0.1); + + Console.WriteLine(string.Join(", ", clusters)); + } + } +} diff --git a/VectoCore/VectoCoreTest/FileIO/JsonReadTest.cs b/VectoCore/VectoCoreTest/FileIO/JsonReadTest.cs index 91155c3cf240a23b5df8ca9c896f73128868bd88..41d759b4f71dcde0454b791a5215bf3e95a08cce 100644 --- a/VectoCore/VectoCoreTest/FileIO/JsonReadTest.cs +++ b/VectoCore/VectoCoreTest/FileIO/JsonReadTest.cs @@ -173,8 +173,7 @@ namespace TUGraz.VectoCore.Tests.FileIO } var gbxData = new EngineeringDataAdapter().CreateGearboxData(inputProvider, MockSimulationDataFactory.CreateEngineDataFromFile(@"TestData\Components\AT_GBX\Engine.veng", 0), 2.1, - 0.5.SI<Meter>(), VehicleCategory.RigidTruck, - true); + 0.5.SI<Meter>(), VehicleCategory.RigidTruck); Assert.AreEqual(ratios.Length, gbxData.Gears.Count); // interpreted as gearbox with first and second gear using TC (due to gear ratios) @@ -198,8 +197,7 @@ namespace TUGraz.VectoCore.Tests.FileIO } var gbxData = new EngineeringDataAdapter().CreateGearboxData(inputProvider, MockSimulationDataFactory.CreateEngineDataFromFile(@"TestData\Components\AT_GBX\Engine.veng", 0), 2.1, - 0.5.SI<Meter>(), VehicleCategory.RigidTruck, - true); + 0.5.SI<Meter>(), VehicleCategory.RigidTruck); Assert.AreEqual(ratios.Length, gbxData.Gears.Count); Assert.IsTrue(gbxData.Gears[1].HasLockedGear); @@ -225,8 +223,7 @@ namespace TUGraz.VectoCore.Tests.FileIO } var gbxData = new EngineeringDataAdapter().CreateGearboxData(inputProvider, MockSimulationDataFactory.CreateEngineDataFromFile(@"TestData\Components\AT_GBX\Engine.veng", 0), 2.1, - 0.5.SI<Meter>(), VehicleCategory.RigidTruck, - true); + 0.5.SI<Meter>(), VehicleCategory.RigidTruck); Assert.AreEqual(ratios.Length, gbxData.Gears.Count); Assert.IsTrue(gbxData.Gears[1].HasLockedGear); @@ -251,8 +248,7 @@ namespace TUGraz.VectoCore.Tests.FileIO } var gbxData = new EngineeringDataAdapter().CreateGearboxData(inputProvider, MockSimulationDataFactory.CreateEngineDataFromFile(@"TestData\Components\AT_GBX\Engine.veng", 0), 2.1, - 0.5.SI<Meter>(), VehicleCategory.RigidTruck, - true); + 0.5.SI<Meter>(), VehicleCategory.RigidTruck); Assert.AreEqual(ratios.Length, gbxData.Gears.Count); Assert.IsFalse(gbxData.Gears[1].HasLockedGear); @@ -279,8 +275,7 @@ namespace TUGraz.VectoCore.Tests.FileIO } var gbxData = new EngineeringDataAdapter().CreateGearboxData(inputProvider, MockSimulationDataFactory.CreateEngineDataFromFile(@"TestData\Components\AT_GBX\Engine.veng", 0), 2.1, - 0.5.SI<Meter>(), VehicleCategory.InterurbanBus, - true); + 0.5.SI<Meter>(), VehicleCategory.InterurbanBus); Assert.AreEqual(ratios.Length, gbxData.Gears.Count); Assert.IsTrue(gbxData.Gears[1].HasLockedGear); @@ -307,8 +302,7 @@ namespace TUGraz.VectoCore.Tests.FileIO } var gbxData = new EngineeringDataAdapter().CreateGearboxData(inputProvider, MockSimulationDataFactory.CreateEngineDataFromFile(@"TestData\Components\AT_GBX\Engine.veng", 0), 2.1, - 0.5.SI<Meter>(), VehicleCategory.InterurbanBus, - true); + 0.5.SI<Meter>(), VehicleCategory.InterurbanBus); Assert.AreEqual(ratios.Length, gbxData.Gears.Count); Assert.IsFalse(gbxData.Gears[1].HasLockedGear); diff --git a/VectoCore/VectoCoreTest/Models/SimulationComponent/GearboxTest.cs b/VectoCore/VectoCoreTest/Models/SimulationComponent/GearboxTest.cs index 9e2fd0e0c38b1580773562bfe333dc4c227dbebc..4bd32375a629848bf95e0b145f5078d0b3c22b16 100644 --- a/VectoCore/VectoCoreTest/Models/SimulationComponent/GearboxTest.cs +++ b/VectoCore/VectoCoreTest/Models/SimulationComponent/GearboxTest.cs @@ -205,7 +205,10 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent } [TestCase(GearboxDataFile, EngineDataFile, 6.38, 2300, 1600, 2356.2326), - TestCase(GearboxDataFile, EngineDataFile, 6.38, -1300, 1000, -1267.0686)] + TestCase(GearboxDataFile, EngineDataFile, 6.38, -1300, 1000, -1267.0686), + // the following entries are beyond the original loss map, but are not 'extrapolated' because the loss-map is extended on reading + TestCase(GearboxDataFile, EngineDataFile, 6.38, 6300, 1600, 6437.86530), + TestCase(GearboxDataFile, EngineDataFile, 6.38, -3300, 1000, -3227.8529411)] public void Gearbox_LossMapInterpolation(string gbxFile, string engineFile, double ratio, double torque, double inAngularSpeed, double expectedTorque) { @@ -228,6 +231,8 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent var n = inAngularSpeed.RPMtoRad(); var response = (ResponseSuccess)gearbox.OutPort().Request(absTime, dt, tq * ratio, n / ratio); + Assert.IsFalse(gearbox.CurrentState.TorqueLossResult.Extrapolated); + AssertHelper.AreRelativeEqual(absTime, port.AbsTime); AssertHelper.AreRelativeEqual(dt, port.Dt); AssertHelper.AreRelativeEqual(inAngularSpeed, port.AngularVelocity.Value() / Constants.RPMToRad); @@ -280,8 +285,8 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent }; } - [TestCase(GearboxDataFile, EngineDataFile, 6.38, 2600, 1600, 2658.1060109), - TestCase(GearboxDataFile, EngineDataFile, 6.38, -2600, 1000, -2543.4076)] + [TestCase(GearboxDataFile, EngineDataFile, 6.38, 9600, 1600, 9756.1054377), + TestCase(GearboxDataFile, EngineDataFile, 6.38, -9600, 1000, -9445.40776858)] public void Gearbox_LossMapExtrapolation_Declaration(string gbxFile, string engineFile, double ratio, double torque, double inAngularSpeed, double expectedTorque) { @@ -305,6 +310,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent var n = inAngularSpeed.RPMtoRad(); var response = (ResponseSuccess)gearbox.OutPort().Request(absTime, dt, tq * ratio, n / ratio); + Assert.IsTrue( gearbox.CurrentState.TorqueLossResult.Extrapolated); Assert.AreEqual(absTime, port.AbsTime); Assert.AreEqual(dt, port.Dt); Assert.AreEqual(inAngularSpeed, port.AngularVelocity.Value() / Constants.RPMToRad, 1e-3); @@ -315,8 +321,8 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent AssertHelper.Exception<VectoException>(() => { gearbox.CommitSimulationStep(modData); }); } - [TestCase(GearboxDataFile, EngineDataFile, 6.38, 2600, 1600, 2658.1060109), - TestCase(GearboxDataFile, EngineDataFile, 6.38, -2600, 1000, -2543.4076)] + [TestCase(GearboxDataFile, EngineDataFile, 6.38, 9600, 1600, 9756.1054377), + TestCase(GearboxDataFile, EngineDataFile, 6.38, -9600, 1000, -9445.40776858)] public void Gearbox_LossMapExtrapolation_Engineering(string gbxFile, string engineFile, double ratio, double torque, double inAngularSpeed, double expectedTorque) { @@ -339,6 +345,8 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent var n = inAngularSpeed.RPMtoRad(); var response = (ResponseSuccess)gearbox.OutPort().Request(absTime, dt, t * ratio, n / ratio); + Assert.IsTrue(gearbox.CurrentState.TorqueLossResult.Extrapolated); + Assert.AreEqual(absTime, port.AbsTime); Assert.AreEqual(dt, port.Dt); Assert.AreEqual(n, port.AngularVelocity); @@ -349,9 +357,9 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent gearbox.CommitSimulationStep(modData); } - [TestCase(GearboxDataFile, EngineDataFile, 6.38, 2600, 1600, true, 2658.1060109), + [TestCase(GearboxDataFile, EngineDataFile, 6.38, 9600, 1600, true, 9756.10543), TestCase(GearboxDataFile, EngineDataFile, 6.38, -2500, 1000, false, -2443.5392), - TestCase(GearboxDataFile, EngineDataFile, 6.38, -1000, 1000, false, -972.95098)] + TestCase(GearboxDataFile, EngineDataFile, 6.38, -3000, 1000, false, -2933.73529)] public void Gearbox_LossMapExtrapolation_DryRun(string gbxFile, string engineFile, double ratio, double torque, double inAngularSpeed, bool extrapolated, double expectedTorque) { @@ -378,8 +386,8 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent Assert.AreEqual(absTime, port.AbsTime); Assert.AreEqual(dt, port.Dt); Assert.AreEqual(n, port.AngularVelocity); - AssertHelper.AreRelativeEqual(expectedTorque.SI<NewtonMeter>(), port.Torque); Assert.AreEqual(extrapolated, gearbox.CurrentState.TorqueLossResult.Extrapolated); + AssertHelper.AreRelativeEqual(expectedTorque.SI<NewtonMeter>(), port.Torque); var modData = new MockModalDataContainer(); gearbox.CommitSimulationStep(modData); diff --git a/VectoCore/VectoCoreTest/Models/SimulationComponentData/GearboxDataTest.cs b/VectoCore/VectoCoreTest/Models/SimulationComponentData/GearboxDataTest.cs index 7a48f865e41e4109b63ae422d0de9ea28448cb8a..513c9acb847bf6f1c50166d9375443d1d7f5b374 100644 --- a/VectoCore/VectoCoreTest/Models/SimulationComponentData/GearboxDataTest.cs +++ b/VectoCore/VectoCoreTest/Models/SimulationComponentData/GearboxDataTest.cs @@ -29,344 +29,383 @@ * Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology */ -using System; -using System.Data; -using NUnit.Framework; -using TUGraz.VectoCommon.Exceptions; -using TUGraz.VectoCommon.Models; -using TUGraz.VectoCommon.Utils; -using TUGraz.VectoCore.InputData.Reader; -using TUGraz.VectoCore.InputData.Reader.ComponentData; -using TUGraz.VectoCore.InputData.Reader.DataObjectAdapter; -using TUGraz.VectoCore.Models.SimulationComponent.Data.Engine; -using TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox; -using TUGraz.VectoCore.Tests.Utils; -using TUGraz.VectoCore.Utils; +using System; +using System.Collections.Generic; +using System.Data; +using NUnit.Framework; +using TUGraz.VectoCommon.Exceptions; +using TUGraz.VectoCommon.Models; +using TUGraz.VectoCommon.Utils; +using TUGraz.VectoCore.InputData.Reader; +using TUGraz.VectoCore.InputData.Reader.ComponentData; +using TUGraz.VectoCore.InputData.Reader.DataObjectAdapter; +using TUGraz.VectoCore.Models.SimulationComponent.Data.Engine; +using TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox; +using TUGraz.VectoCore.Tests.Utils; +using TUGraz.VectoCore.Utils; using System.IO; +using System.Linq; +using System.Windows.Forms; +using System.Xml; +using System.Xml.Linq; +using System.Xml.XPath; +using TUGraz.VectoCore.Tests.Reports; + +namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData +{ + [TestFixture] + public class GearboxDataTest + { + protected const string GearboxFile = @"Testdata\Components\24t Coach.vgbx"; + + protected const string EngineFile = @"TestData\Components\24t Coach.veng"; + + [OneTimeSetUp] + public void RunBeforeAnyTests() + { + Directory.SetCurrentDirectory(TestContext.CurrentContext.TestDirectory); + } + + + [TestCase] + public void TestGearboxDataReadTest() + { + var axleData = MockSimulationDataFactory.CreateAxleGearDataFromFile(GearboxFile); + Assert.AreEqual(3.240355, axleData.AxleGear.Ratio, 0.0001); + + var gbxData = MockSimulationDataFactory.CreateGearboxDataFromFile(GearboxFile, EngineFile, false); + Assert.AreEqual(GearboxType.AMT, gbxData.Type); + Assert.AreEqual(1.0, gbxData.TractionInterruption.Value(), 0.0001); + Assert.AreEqual(8, gbxData.Gears.Count); + + Assert.AreEqual(1.0, gbxData.Gears[7].Ratio, 0.0001); + + Assert.AreEqual(-400, gbxData.Gears[1].ShiftPolygon.Downshift[0].Torque.Value(), 0.0001); + Assert.AreEqual(560.RPMtoRad().Value(), gbxData.Gears[1].ShiftPolygon.Downshift[0].AngularSpeed.Value(), 0.0001); + Assert.AreEqual(1289.RPMtoRad().Value(), gbxData.Gears[1].ShiftPolygon.Upshift[0].AngularSpeed.Value(), 0.0001); + + Assert.AreEqual(200.RPMtoRad().Value(), gbxData.Gears[1].LossMap[26].InputSpeed.Value(), 0.0001); + Assert.AreEqual(-350, gbxData.Gears[1].LossMap[35].InputTorque.Value(), 0.0001); + Assert.AreEqual(13.072, gbxData.Gears[1].LossMap[35].TorqueLoss.Value(), 0.0001); + } + + [TestCase("Test1", @"TestData\Components\24t Coach.vgbx", 520, 20.320, "A", 279698.4, 9401.44062)] + [TestCase("Test2", @"TestData\Components\24t Coach.vgbx", 520, 0.5858335, "A", 17173.5, 409.773677587509)] + [TestCase("Test3", @"TestData\Components\24t Coach.vgbx", 520, 0.3996113, "A", 292.5253, 118.282541632652)] + [TestCase("Test4", @"TestData\Components\24t Coach.vgbx", 520, 5.327739, "A", 57431.12, 2222.78785705566)] + [TestCase("Test5", @"TestData\Components\24t Coach.vgbx", 520, 5.661779, "A", 73563.93, 2553.00283432007)] + [TestCase("Test6", @"TestData\Components\24t Coach.vgbx", 520, 14.15156, "A", 212829.5, 6822.16882705688)] + [TestCase("Test7", @"TestData\Components\24t Coach.vgbx", 520, 14.55574, "A", 15225.52, 4308.41207504272)] + [TestCase("Test8", @"TestData\Components\24t Coach.vgbx", 520, 4.601774, "A", -1240.225, 1362.09738254547)] + [TestCase("Test9", @"TestData\Components\24t Coach.vgbx", 520, 3.934339, "A", -698.5989, 1164.5405292511)] + public void TestInterpolation(string testName, string gearboxDataFile, double rDyn, double v, string gear, + double powerGbxOut, double gbxPowerLoss) + { + var rdyn = rDyn; + + var angSpeed = (60 * v / (2 * rdyn * Math.PI / 1000)).RPMtoRad(); + + var axleData = MockSimulationDataFactory.CreateAxleGearDataFromFile(gearboxDataFile); + + var pvD = powerGbxOut.SI<Watt>(); + + var torqueToWheels = Formulas.PowerToTorque(pvD, angSpeed); + var torqueFromEngine = 0.SI<NewtonMeter>(); + + if (gear == "A") { + torqueFromEngine = torqueToWheels / axleData.AxleGear.Ratio; + torqueFromEngine += axleData.AxleGear.LossMap.GetTorqueLoss(angSpeed, torqueToWheels).Value; + } + + var powerEngine = Formulas.TorqueToPower(torqueFromEngine, angSpeed * axleData.AxleGear.Ratio); + var loss = powerEngine - pvD; + + Assert.AreEqual(gbxPowerLoss, loss.Value(), 0.1, testName); + } + + [TestCase] + public void TestLossMap_IN_10_CONST_Interpolation_Extrapolation() + { + var data = new DataTable(); + data.Columns.Add(""); + data.Columns.Add(""); + data.Columns.Add(""); + data.Rows.Add("0", "0", "10"); // (0,100):10 -- (100,100):10 + data.Rows.Add("0", "100", "10"); // | \ | + data.Rows.Add("100", "0", "10"); // | \ | + data.Rows.Add("100", "100", "10"); // (0,0):10 ----- (100,10):10 + + var map = TransmissionLossMapReader.Create(data, 1.0, "1"); + + // test inside the triangles + AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(25.RPMtoRad(), 25.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(75.RPMtoRad(), 50.SI<NewtonMeter>()).Value); + + // test interpolation on edges + AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(50.RPMtoRad(), -5.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(0.RPMtoRad(), 45.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(50.RPMtoRad(), 40.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(50.RPMtoRad(), 75.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(100.RPMtoRad(), 25.SI<NewtonMeter>()).Value); + + // test interpolation on corner points + AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(0.RPMtoRad(), 0.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(0.RPMtoRad(), 90.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(100.RPMtoRad(), -10.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(100.RPMtoRad(), 60.SI<NewtonMeter>()).Value); + + // test outside the corners + AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(-20.RPMtoRad(), -20.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(-20.RPMtoRad(), 120.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(120.RPMtoRad(), -20.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(120.RPMtoRad(), 120.SI<NewtonMeter>()).Value); + + // test outside the edges + AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(-20.RPMtoRad(), 50.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(50.RPMtoRad(), 120.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(50.RPMtoRad(), -20.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(120.RPMtoRad(), 50.SI<NewtonMeter>()).Value); + } + + [TestCase] + public void TestLossMap_OUT_10_CONST_Interpolation_Extrapolation() + { + var data = new DataTable(); + data.Columns.Add(""); + data.Columns.Add(""); + data.Columns.Add(""); + data.Rows.Add("0", "0", "10"); // (0,100):10 -- (100,100):10 + data.Rows.Add("0", "100", "10"); // | \ | + data.Rows.Add("100", "0", "10"); // | \ | + data.Rows.Add("100", "100", "10"); // (0,0):10 ----- (100,10):10 + + var map = TransmissionLossMapReader.Create(data, 1.0, "1"); + + // test inside the triangles + AssertHelper.AreRelativeEqual(15, map.GetOutTorque(25.RPMtoRad(), 25.SI<NewtonMeter>(), true)); + AssertHelper.AreRelativeEqual(40, map.GetOutTorque(75.RPMtoRad(), 50.SI<NewtonMeter>(), true)); + + // test interpolation on edges + AssertHelper.AreRelativeEqual(-15, map.GetOutTorque(50.RPMtoRad(), -5.SI<NewtonMeter>(), true)); + AssertHelper.AreRelativeEqual(35, map.GetOutTorque(0.RPMtoRad(), 45.SI<NewtonMeter>(), true)); + AssertHelper.AreRelativeEqual(30, map.GetOutTorque(50.RPMtoRad(), 40.SI<NewtonMeter>(), true)); + AssertHelper.AreRelativeEqual(65, map.GetOutTorque(50.RPMtoRad(), 75.SI<NewtonMeter>(), true)); + AssertHelper.AreRelativeEqual(15, map.GetOutTorque(100.RPMtoRad(), 25.SI<NewtonMeter>(), true)); + + // test interpolation on corner points + AssertHelper.AreRelativeEqual(-10, map.GetOutTorque(0.RPMtoRad(), 0.SI<NewtonMeter>(), true)); + AssertHelper.AreRelativeEqual(80, map.GetOutTorque(0.RPMtoRad(), 90.SI<NewtonMeter>(), true)); + AssertHelper.AreRelativeEqual(-20, map.GetOutTorque(100.RPMtoRad(), -10.SI<NewtonMeter>(), true)); + AssertHelper.AreRelativeEqual(50, map.GetOutTorque(100.RPMtoRad(), 60.SI<NewtonMeter>(), true)); + + // test outside the corners + AssertHelper.AreRelativeEqual(-30, map.GetOutTorque(-20.RPMtoRad(), -20.SI<NewtonMeter>(), true)); + AssertHelper.AreRelativeEqual(110, map.GetOutTorque(-20.RPMtoRad(), 120.SI<NewtonMeter>(), true)); + AssertHelper.AreRelativeEqual(-30, map.GetOutTorque(120.RPMtoRad(), -20.SI<NewtonMeter>(), true)); + AssertHelper.AreRelativeEqual(110, map.GetOutTorque(120.RPMtoRad(), 120.SI<NewtonMeter>(), true)); + + // test outside the edges + AssertHelper.AreRelativeEqual(40, map.GetOutTorque(-20.RPMtoRad(), 50.SI<NewtonMeter>(), true)); + AssertHelper.AreRelativeEqual(110, map.GetOutTorque(50.RPMtoRad(), 120.SI<NewtonMeter>(), true)); + AssertHelper.AreRelativeEqual(-30, map.GetOutTorque(50.RPMtoRad(), -20.SI<NewtonMeter>(), true)); + AssertHelper.AreRelativeEqual(40, map.GetOutTorque(120.RPMtoRad(), 50.SI<NewtonMeter>(), true)); + } + + [TestCase] + public void TestLossMap_IN_Interpolation_Extrapolation() + { + var data = new DataTable(); + data.Columns.Add(""); + data.Columns.Add(""); + data.Columns.Add(""); + data.Rows.Add("0", "0", "0"); // (0,110):10 -- (100,140):40 + data.Rows.Add("0", "110", "10"); // | \ | + data.Rows.Add("100", "10", "10"); // | \ | + data.Rows.Add("100", "140", "40"); // (0,0):0 ----- (100,10):10 + + var map = TransmissionLossMapReader.Create(data, 1.0, "1"); + + // test inside the triangles + AssertHelper.AreRelativeEqual(5, map.GetTorqueLoss(25.RPMtoRad(), 25.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(17.5, map.GetTorqueLoss(75.RPMtoRad(), 50.SI<NewtonMeter>()).Value); + + // test interpolation on edges + AssertHelper.AreRelativeEqual(5, map.GetTorqueLoss(50.RPMtoRad(), -5.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(4.5, map.GetTorqueLoss(0.RPMtoRad(), 45.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(9, map.GetTorqueLoss(50.RPMtoRad(), 40.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(17.5, map.GetTorqueLoss(50.RPMtoRad(), 75.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(17.5, map.GetTorqueLoss(100.RPMtoRad(), 25.SI<NewtonMeter>()).Value); + + // test interpolation on corner points + AssertHelper.AreRelativeEqual(0, map.GetTorqueLoss(0.RPMtoRad(), 0.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(9, map.GetTorqueLoss(0.RPMtoRad(), 90.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(100.RPMtoRad(), -10.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(28, map.GetTorqueLoss(100.RPMtoRad(), 60.SI<NewtonMeter>()).Value); + + // test outside the corners + AssertHelper.AreRelativeEqual(0, map.GetTorqueLoss(-20.RPMtoRad(), -20.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(-20.RPMtoRad(), 120.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(120.RPMtoRad(), -20.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(40, map.GetTorqueLoss(120.RPMtoRad(), 120.SI<NewtonMeter>()).Value); + + // test outside the edges + AssertHelper.AreRelativeEqual(5, map.GetTorqueLoss(-20.RPMtoRad(), 50.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(25, map.GetTorqueLoss(50.RPMtoRad(), 120.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(5, map.GetTorqueLoss(50.RPMtoRad(), -20.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(25, map.GetTorqueLoss(120.RPMtoRad(), 50.SI<NewtonMeter>()).Value); + } + + [TestCase] + public void TestLossMap_OUT_Interpolation_Extrapolation() + { + var data = new DataTable(); + data.Columns.Add(""); + data.Columns.Add(""); + data.Columns.Add(""); + data.Rows.Add("0", "0", "0"); // (0,100):10 -- (100,100):40 + data.Rows.Add("0", "100", "10"); // | \ | + data.Rows.Add("100", "0", "10"); // | \ | + data.Rows.Add("100", "100", "40"); // (0,0):0 ----- (100,0):10 + + var map = TransmissionLossMapReader.Create(data, 1.0, "1"); + + // test inside the triangles + AssertHelper.AreRelativeEqual(20, map.GetOutTorque(25.RPMtoRad(), 25.SI<NewtonMeter>())); + AssertHelper.AreRelativeEqual(32.5, map.GetOutTorque(75.RPMtoRad(), 50.SI<NewtonMeter>())); + + // test interpolation on edges + AssertHelper.AreRelativeEqual(-5, map.GetOutTorque(50.RPMtoRad(), 0.SI<NewtonMeter>())); + AssertHelper.AreRelativeEqual(40.5, map.GetOutTorque(0.RPMtoRad(), 45.SI<NewtonMeter>())); + AssertHelper.AreRelativeEqual(31, map.GetOutTorque(50.RPMtoRad(), 40.SI<NewtonMeter>())); + AssertHelper.AreRelativeEqual(57.5, map.GetOutTorque(50.RPMtoRad(), 75.SI<NewtonMeter>())); + AssertHelper.AreRelativeEqual(7.5, map.GetOutTorque(100.RPMtoRad(), 25.SI<NewtonMeter>())); + + // test interpolation on corner points + AssertHelper.AreRelativeEqual(0, map.GetTorqueLoss(0.RPMtoRad(), 0.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(0.RPMtoRad(), 90.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(100.RPMtoRad(), -10.SI<NewtonMeter>()).Value); + AssertHelper.AreRelativeEqual(40, map.GetTorqueLoss(100.RPMtoRad(), 60.SI<NewtonMeter>()).Value); + + // test outside the corners + AssertHelper.AreRelativeEqual(-20, map.GetOutTorque(-20.RPMtoRad(), -20.SI<NewtonMeter>(), true)); + AssertHelper.AreRelativeEqual(110, map.GetOutTorque(-20.RPMtoRad(), 120.SI<NewtonMeter>(), true)); + AssertHelper.AreRelativeEqual(-30, map.GetOutTorque(120.RPMtoRad(), -20.SI<NewtonMeter>(), true)); + AssertHelper.AreRelativeEqual(80, map.GetOutTorque(120.RPMtoRad(), 120.SI<NewtonMeter>(), true)); + + // test outside the edges + AssertHelper.AreRelativeEqual(45, map.GetOutTorque(-20.RPMtoRad(), 50.SI<NewtonMeter>(), true)); + AssertHelper.AreRelativeEqual(95, map.GetOutTorque(50.RPMtoRad(), 120.SI<NewtonMeter>(), true)); + AssertHelper.AreRelativeEqual(-25, map.GetOutTorque(50.RPMtoRad(), -20.SI<NewtonMeter>(), true)); + AssertHelper.AreRelativeEqual(25, map.GetOutTorque(120.RPMtoRad(), 50.SI<NewtonMeter>(), true)); + + // test extrapolation not allowed + AssertHelper.Exception<VectoException>(() => { map.GetOutTorque(120.RPMtoRad(), 50.SI<NewtonMeter>()); }); + } + + [TestCase] + public void TestFullLoadCurveIntersection() + { + var engineFldString = new[] { + "560, 1180, -149", + "600, 1282, -148", + "800, 1791, -149", + "1000, 2300, -160", + "1200, 2300, -179", + "1400, 2300, -203", + "1600, 2079, -235", + "1800, 1857, -264", + "2000, 1352, -301", + "2100, 1100, -320", + }; + var dataEng = + VectoCSVFile.ReadStream(InputDataHelper.InputDataAsStream("n [U/min],Mfull [Nm],Mdrag [Nm]", engineFldString)); + var engineFld = FullLoadCurveReader.Create(dataEng, true); + + + var fullLoadCurve = AbstractSimulationDataAdapter.IntersectFullLoadCurves(engineFld, 2500.SI<NewtonMeter>()); + + Assert.AreEqual(10, fullLoadCurve.FullLoadEntries.Count); + + Assert.AreEqual(1180.0, fullLoadCurve.FullLoadStationaryTorque(560.RPMtoRad()).Value()); + Assert.AreEqual(1100.0, fullLoadCurve.FullLoadStationaryTorque(2100.RPMtoRad()).Value()); + } + + /// <summary> + /// VECTO-190 + /// </summary> + [TestCase] + public void TestFullLoadSorting() + { + var gbxFldString = new[] { + "600, 1000, -100", + "2400, 2000, -120", + "1000, 500, -110" + }; + + var dataGbx = + VectoCSVFile.ReadStream(InputDataHelper.InputDataAsStream("n [U/min],Mfull [Nm], Mdrag [Nm]", gbxFldString)); + var gbxFld = FullLoadCurveReader.Create(dataGbx, true); + + var maxTorque = gbxFld.FullLoadStationaryTorque(800.RPMtoRad()); + Assert.AreEqual(750, maxTorque.Value()); + } + + [TestCase()] + public void TestLossMapExtension() + { + var gbxFile = @"TestData\Components\Indirect Gear.vtlm"; + + var lossMapOrig = TransmissionLossMapReader.ReadFromFile(gbxFile, 1.0, "origLossMap"); + var extendedMap = TransmissionLossMapReader.ReadFromFile(gbxFile, 1.0, "origLossMap", true); + + var rpm = 100.RPMtoRad(); + var tq = -3000.SI<NewtonMeter>(); + var lookupOrig = lossMapOrig.GetTorqueLoss(rpm, tq); + var lookupExt = extendedMap.GetTorqueLoss(rpm, tq); + + //foreach (var entry in gearboxDataExt.Gears[7].LossMap._entries) { + // Console.WriteLine(string.Format("{0},{1},{2}", entry.InputSpeed.AsRPM, entry.InputTorque.Value(), entry.TorqueLoss.Value())); + //} + + Assert.IsTrue(lookupOrig.Extrapolated); + Assert.IsFalse(lookupExt.Extrapolated); + + rpm = 1200.RPMtoRad(); + lookupOrig = lossMapOrig.GetTorqueLoss(rpm, tq); + lookupExt = extendedMap.GetTorqueLoss(rpm, tq); + + Assert.IsTrue(lookupOrig.Extrapolated); + Assert.IsFalse(lookupExt.Extrapolated); + } + + [TestCase()] + public void TestAxlegearLossMapExtension() + { + var lossMapFile = @"TestData\Components\Axle.vtlm"; + + var origLossMap = TransmissionLossMapReader.ReadFromFile(lossMapFile, 3.240355, "AxleOrig"); + var extendedLossMap = TransmissionLossMapReader.ReadFromFile(lossMapFile, 3.240355, "AxleExtended", true); + + //foreach (var entry in gearboxDataExt.AxleGear.LossMap._entries) { + // Console.WriteLine(string.Format("{0},{1},{2}", entry.InputSpeed.AsRPM, entry.InputTorque.Value(), entry.TorqueLoss.Value())); + //} + + var rpm = 100.RPMtoRad(); + var tq = 80000.SI<NewtonMeter>(); + var lookupOrig = origLossMap.GetTorqueLoss(rpm, tq); + var lookupExt = extendedLossMap.GetTorqueLoss(rpm, tq); + + Assert.IsTrue(lookupOrig.Extrapolated); + Assert.IsFalse(lookupExt.Extrapolated); + + rpm = 1000.RPMtoRad(); + lookupOrig = origLossMap.GetTorqueLoss(rpm, tq); + lookupExt = extendedLossMap.GetTorqueLoss(rpm, tq); + + Assert.IsTrue(lookupOrig.Extrapolated); + Assert.IsFalse(lookupExt.Extrapolated); + } + + } -namespace TUGraz.VectoCore.Tests.Models.SimulationComponentData -{ - [TestFixture] - public class GearboxDataTest - { - protected const string GearboxFile = @"Testdata\Components\24t Coach.vgbx"; - - protected const string EngineFile = @"TestData\Components\24t Coach.veng"; - - [OneTimeSetUp] - public void RunBeforeAnyTests() - { - Directory.SetCurrentDirectory(TestContext.CurrentContext.TestDirectory); - } - - - [TestCase] - public void TestGearboxDataReadTest() - { - var axleData = MockSimulationDataFactory.CreateAxleGearDataFromFile(GearboxFile); - Assert.AreEqual(3.240355, axleData.AxleGear.Ratio, 0.0001); - - var gbxData = MockSimulationDataFactory.CreateGearboxDataFromFile(GearboxFile, EngineFile, false); - Assert.AreEqual(GearboxType.AMT, gbxData.Type); - Assert.AreEqual(1.0, gbxData.TractionInterruption.Value(), 0.0001); - Assert.AreEqual(8, gbxData.Gears.Count); - - Assert.AreEqual(1.0, gbxData.Gears[7].Ratio, 0.0001); - - Assert.AreEqual(-400, gbxData.Gears[1].ShiftPolygon.Downshift[0].Torque.Value(), 0.0001); - Assert.AreEqual(560.RPMtoRad().Value(), gbxData.Gears[1].ShiftPolygon.Downshift[0].AngularSpeed.Value(), 0.0001); - Assert.AreEqual(1289.RPMtoRad().Value(), gbxData.Gears[1].ShiftPolygon.Upshift[0].AngularSpeed.Value(), 0.0001); - - Assert.AreEqual(200.RPMtoRad().Value(), gbxData.Gears[1].LossMap[26].InputSpeed.Value(), 0.0001); - Assert.AreEqual(-350, gbxData.Gears[1].LossMap[35].InputTorque.Value(), 0.0001); - Assert.AreEqual(13.072, gbxData.Gears[1].LossMap[35].TorqueLoss.Value(), 0.0001); - } - - [TestCase("Test1", @"TestData\Components\24t Coach.vgbx", 520, 20.320, "A", 279698.4, 9401.44062)] - [TestCase("Test2", @"TestData\Components\24t Coach.vgbx", 520, 0.5858335, "A", 17173.5, 409.773677587509)] - [TestCase("Test3", @"TestData\Components\24t Coach.vgbx", 520, 0.3996113, "A", 292.5253, 118.282541632652)] - [TestCase("Test4", @"TestData\Components\24t Coach.vgbx", 520, 5.327739, "A", 57431.12, 2222.78785705566)] - [TestCase("Test5", @"TestData\Components\24t Coach.vgbx", 520, 5.661779, "A", 73563.93, 2553.00283432007)] - [TestCase("Test6", @"TestData\Components\24t Coach.vgbx", 520, 14.15156, "A", 212829.5, 6822.16882705688)] - [TestCase("Test7", @"TestData\Components\24t Coach.vgbx", 520, 14.55574, "A", 15225.52, 4308.41207504272)] - [TestCase("Test8", @"TestData\Components\24t Coach.vgbx", 520, 4.601774, "A", -1240.225, 1362.09738254547)] - [TestCase("Test9", @"TestData\Components\24t Coach.vgbx", 520, 3.934339, "A", -698.5989, 1164.5405292511)] - public void TestInterpolation(string testName, string gearboxDataFile, double rDyn, double v, string gear, - double powerGbxOut, double gbxPowerLoss) - { - var rdyn = rDyn; - - var angSpeed = (60 * v / (2 * rdyn * Math.PI / 1000)).RPMtoRad(); - - var axleData = MockSimulationDataFactory.CreateAxleGearDataFromFile(gearboxDataFile); - - var pvD = powerGbxOut.SI<Watt>(); - - var torqueToWheels = Formulas.PowerToTorque(pvD, angSpeed); - var torqueFromEngine = 0.SI<NewtonMeter>(); - - if (gear == "A") { - torqueFromEngine = torqueToWheels / axleData.AxleGear.Ratio; - torqueFromEngine += axleData.AxleGear.LossMap.GetTorqueLoss(angSpeed, torqueToWheels).Value; - } - - var powerEngine = Formulas.TorqueToPower(torqueFromEngine, angSpeed * axleData.AxleGear.Ratio); - var loss = powerEngine - pvD; - - Assert.AreEqual(gbxPowerLoss, loss.Value(), 0.1, testName); - } - - [TestCase] - public void TestLossMap_IN_10_CONST_Interpolation_Extrapolation() - { - var data = new DataTable(); - data.Columns.Add(""); - data.Columns.Add(""); - data.Columns.Add(""); - data.Rows.Add("0", "0", "10"); // (0,100):10 -- (100,100):10 - data.Rows.Add("0", "100", "10"); // | \ | - data.Rows.Add("100", "0", "10"); // | \ | - data.Rows.Add("100", "100", "10"); // (0,0):10 ----- (100,10):10 - - var map = TransmissionLossMapReader.Create(data, 1.0, "1"); - - // test inside the triangles - AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(25.RPMtoRad(), 25.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(75.RPMtoRad(), 50.SI<NewtonMeter>()).Value); - - // test interpolation on edges - AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(50.RPMtoRad(), -5.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(0.RPMtoRad(), 45.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(50.RPMtoRad(), 40.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(50.RPMtoRad(), 75.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(100.RPMtoRad(), 25.SI<NewtonMeter>()).Value); - - // test interpolation on corner points - AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(0.RPMtoRad(), 0.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(0.RPMtoRad(), 90.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(100.RPMtoRad(), -10.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(100.RPMtoRad(), 60.SI<NewtonMeter>()).Value); - - // test outside the corners - AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(-20.RPMtoRad(), -20.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(-20.RPMtoRad(), 120.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(120.RPMtoRad(), -20.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(120.RPMtoRad(), 120.SI<NewtonMeter>()).Value); - - // test outside the edges - AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(-20.RPMtoRad(), 50.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(50.RPMtoRad(), 120.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(50.RPMtoRad(), -20.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(120.RPMtoRad(), 50.SI<NewtonMeter>()).Value); - } - - [TestCase] - public void TestLossMap_OUT_10_CONST_Interpolation_Extrapolation() - { - var data = new DataTable(); - data.Columns.Add(""); - data.Columns.Add(""); - data.Columns.Add(""); - data.Rows.Add("0", "0", "10"); // (0,100):10 -- (100,100):10 - data.Rows.Add("0", "100", "10"); // | \ | - data.Rows.Add("100", "0", "10"); // | \ | - data.Rows.Add("100", "100", "10"); // (0,0):10 ----- (100,10):10 - - var map = TransmissionLossMapReader.Create(data, 1.0, "1"); - - // test inside the triangles - AssertHelper.AreRelativeEqual(15, map.GetOutTorque(25.RPMtoRad(), 25.SI<NewtonMeter>(), true)); - AssertHelper.AreRelativeEqual(40, map.GetOutTorque(75.RPMtoRad(), 50.SI<NewtonMeter>(), true)); - - // test interpolation on edges - AssertHelper.AreRelativeEqual(-15, map.GetOutTorque(50.RPMtoRad(), -5.SI<NewtonMeter>(), true)); - AssertHelper.AreRelativeEqual(35, map.GetOutTorque(0.RPMtoRad(), 45.SI<NewtonMeter>(), true)); - AssertHelper.AreRelativeEqual(30, map.GetOutTorque(50.RPMtoRad(), 40.SI<NewtonMeter>(), true)); - AssertHelper.AreRelativeEqual(65, map.GetOutTorque(50.RPMtoRad(), 75.SI<NewtonMeter>(), true)); - AssertHelper.AreRelativeEqual(15, map.GetOutTorque(100.RPMtoRad(), 25.SI<NewtonMeter>(), true)); - - // test interpolation on corner points - AssertHelper.AreRelativeEqual(-10, map.GetOutTorque(0.RPMtoRad(), 0.SI<NewtonMeter>(), true)); - AssertHelper.AreRelativeEqual(80, map.GetOutTorque(0.RPMtoRad(), 90.SI<NewtonMeter>(), true)); - AssertHelper.AreRelativeEqual(-20, map.GetOutTorque(100.RPMtoRad(), -10.SI<NewtonMeter>(), true)); - AssertHelper.AreRelativeEqual(50, map.GetOutTorque(100.RPMtoRad(), 60.SI<NewtonMeter>(), true)); - - // test outside the corners - AssertHelper.AreRelativeEqual(-30, map.GetOutTorque(-20.RPMtoRad(), -20.SI<NewtonMeter>(), true)); - AssertHelper.AreRelativeEqual(110, map.GetOutTorque(-20.RPMtoRad(), 120.SI<NewtonMeter>(), true)); - AssertHelper.AreRelativeEqual(-30, map.GetOutTorque(120.RPMtoRad(), -20.SI<NewtonMeter>(), true)); - AssertHelper.AreRelativeEqual(110, map.GetOutTorque(120.RPMtoRad(), 120.SI<NewtonMeter>(), true)); - - // test outside the edges - AssertHelper.AreRelativeEqual(40, map.GetOutTorque(-20.RPMtoRad(), 50.SI<NewtonMeter>(), true)); - AssertHelper.AreRelativeEqual(110, map.GetOutTorque(50.RPMtoRad(), 120.SI<NewtonMeter>(), true)); - AssertHelper.AreRelativeEqual(-30, map.GetOutTorque(50.RPMtoRad(), -20.SI<NewtonMeter>(), true)); - AssertHelper.AreRelativeEqual(40, map.GetOutTorque(120.RPMtoRad(), 50.SI<NewtonMeter>(), true)); - } - - [TestCase] - public void TestLossMap_IN_Interpolation_Extrapolation() - { - var data = new DataTable(); - data.Columns.Add(""); - data.Columns.Add(""); - data.Columns.Add(""); - data.Rows.Add("0", "0", "0"); // (0,110):10 -- (100,140):40 - data.Rows.Add("0", "110", "10"); // | \ | - data.Rows.Add("100", "10", "10"); // | \ | - data.Rows.Add("100", "140", "40"); // (0,0):0 ----- (100,10):10 - - var map = TransmissionLossMapReader.Create(data, 1.0, "1"); - - // test inside the triangles - AssertHelper.AreRelativeEqual(5, map.GetTorqueLoss(25.RPMtoRad(), 25.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(17.5, map.GetTorqueLoss(75.RPMtoRad(), 50.SI<NewtonMeter>()).Value); - - // test interpolation on edges - AssertHelper.AreRelativeEqual(5, map.GetTorqueLoss(50.RPMtoRad(), -5.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(4.5, map.GetTorqueLoss(0.RPMtoRad(), 45.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(9, map.GetTorqueLoss(50.RPMtoRad(), 40.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(17.5, map.GetTorqueLoss(50.RPMtoRad(), 75.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(17.5, map.GetTorqueLoss(100.RPMtoRad(), 25.SI<NewtonMeter>()).Value); - - // test interpolation on corner points - AssertHelper.AreRelativeEqual(0, map.GetTorqueLoss(0.RPMtoRad(), 0.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(9, map.GetTorqueLoss(0.RPMtoRad(), 90.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(100.RPMtoRad(), -10.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(28, map.GetTorqueLoss(100.RPMtoRad(), 60.SI<NewtonMeter>()).Value); - - // test outside the corners - AssertHelper.AreRelativeEqual(0, map.GetTorqueLoss(-20.RPMtoRad(), -20.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(-20.RPMtoRad(), 120.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(120.RPMtoRad(), -20.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(40, map.GetTorqueLoss(120.RPMtoRad(), 120.SI<NewtonMeter>()).Value); - - // test outside the edges - AssertHelper.AreRelativeEqual(5, map.GetTorqueLoss(-20.RPMtoRad(), 50.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(25, map.GetTorqueLoss(50.RPMtoRad(), 120.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(5, map.GetTorqueLoss(50.RPMtoRad(), -20.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(25, map.GetTorqueLoss(120.RPMtoRad(), 50.SI<NewtonMeter>()).Value); - } - - [TestCase] - public void TestLossMap_OUT_Interpolation_Extrapolation() - { - var data = new DataTable(); - data.Columns.Add(""); - data.Columns.Add(""); - data.Columns.Add(""); - data.Rows.Add("0", "0", "0"); // (0,100):10 -- (100,100):40 - data.Rows.Add("0", "100", "10"); // | \ | - data.Rows.Add("100", "0", "10"); // | \ | - data.Rows.Add("100", "100", "40"); // (0,0):0 ----- (100,0):10 - - var map = TransmissionLossMapReader.Create(data, 1.0, "1"); - - // test inside the triangles - AssertHelper.AreRelativeEqual(20, map.GetOutTorque(25.RPMtoRad(), 25.SI<NewtonMeter>())); - AssertHelper.AreRelativeEqual(32.5, map.GetOutTorque(75.RPMtoRad(), 50.SI<NewtonMeter>())); - - // test interpolation on edges - AssertHelper.AreRelativeEqual(-5, map.GetOutTorque(50.RPMtoRad(), 0.SI<NewtonMeter>())); - AssertHelper.AreRelativeEqual(40.5, map.GetOutTorque(0.RPMtoRad(), 45.SI<NewtonMeter>())); - AssertHelper.AreRelativeEqual(31, map.GetOutTorque(50.RPMtoRad(), 40.SI<NewtonMeter>())); - AssertHelper.AreRelativeEqual(57.5, map.GetOutTorque(50.RPMtoRad(), 75.SI<NewtonMeter>())); - AssertHelper.AreRelativeEqual(7.5, map.GetOutTorque(100.RPMtoRad(), 25.SI<NewtonMeter>())); - - // test interpolation on corner points - AssertHelper.AreRelativeEqual(0, map.GetTorqueLoss(0.RPMtoRad(), 0.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(0.RPMtoRad(), 90.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(10, map.GetTorqueLoss(100.RPMtoRad(), -10.SI<NewtonMeter>()).Value); - AssertHelper.AreRelativeEqual(40, map.GetTorqueLoss(100.RPMtoRad(), 60.SI<NewtonMeter>()).Value); - - // test outside the corners - AssertHelper.AreRelativeEqual(-20, map.GetOutTorque(-20.RPMtoRad(), -20.SI<NewtonMeter>(), true)); - AssertHelper.AreRelativeEqual(110, map.GetOutTorque(-20.RPMtoRad(), 120.SI<NewtonMeter>(), true)); - AssertHelper.AreRelativeEqual(-30, map.GetOutTorque(120.RPMtoRad(), -20.SI<NewtonMeter>(), true)); - AssertHelper.AreRelativeEqual(80, map.GetOutTorque(120.RPMtoRad(), 120.SI<NewtonMeter>(), true)); - - // test outside the edges - AssertHelper.AreRelativeEqual(45, map.GetOutTorque(-20.RPMtoRad(), 50.SI<NewtonMeter>(), true)); - AssertHelper.AreRelativeEqual(95, map.GetOutTorque(50.RPMtoRad(), 120.SI<NewtonMeter>(), true)); - AssertHelper.AreRelativeEqual(-25, map.GetOutTorque(50.RPMtoRad(), -20.SI<NewtonMeter>(), true)); - AssertHelper.AreRelativeEqual(25, map.GetOutTorque(120.RPMtoRad(), 50.SI<NewtonMeter>(), true)); - - // test extrapolation not allowed - AssertHelper.Exception<VectoException>(() => { map.GetOutTorque(120.RPMtoRad(), 50.SI<NewtonMeter>()); }); - } - - [TestCase] - public void TestFullLoadCurveIntersection() - { - var engineFldString = new[] { - "560, 1180, -149", - "600, 1282, -148", - "800, 1791, -149", - "1000, 2300, -160", - "1200, 2300, -179", - "1400, 2300, -203", - "1600, 2079, -235", - "1800, 1857, -264", - "2000, 1352, -301", - "2100, 1100, -320", - }; - var dataEng = - VectoCSVFile.ReadStream(InputDataHelper.InputDataAsStream("n [U/min],Mfull [Nm],Mdrag [Nm]", engineFldString)); - var engineFld = FullLoadCurveReader.Create(dataEng, true); - - - var fullLoadCurve = AbstractSimulationDataAdapter.IntersectFullLoadCurves(engineFld, 2500.SI<NewtonMeter>()); - - Assert.AreEqual(10, fullLoadCurve.FullLoadEntries.Count); - - Assert.AreEqual(1180.0, fullLoadCurve.FullLoadStationaryTorque(560.RPMtoRad()).Value()); - Assert.AreEqual(1100.0, fullLoadCurve.FullLoadStationaryTorque(2100.RPMtoRad()).Value()); - } - - /// <summary> - /// VECTO-190 - /// </summary> - [TestCase] - public void TestFullLoadSorting() - { - var gbxFldString = new[] { - "600, 1000, -100", - "2400, 2000, -120", - "1000, 500, -110" - }; - - var dataGbx = - VectoCSVFile.ReadStream(InputDataHelper.InputDataAsStream("n [U/min],Mfull [Nm], Mdrag [Nm]", gbxFldString)); - var gbxFld = FullLoadCurveReader.Create(dataGbx, true); - - var maxTorque = gbxFld.FullLoadStationaryTorque(800.RPMtoRad()); - Assert.AreEqual(750, maxTorque.Value()); - } - - [TestCase()] - public void TestLossMapExtension() - { - var gbxFile = @"TestData\Components\24t Coach.vgbx"; - var engineFile = @"TestData\Components\24t Coach.veng"; - - var gearboxDataOrig = MockSimulationDataFactory.CreateGearboxDataFromFile(gbxFile, engineFile, false); - // read loss-map in declaration mode to extrapolate on reading. - var gearboxDataExt = MockSimulationDataFactory.CreateGearboxDataFromFile(gbxFile, engineFile, true); - - var rpm = 100.RPMtoRad(); - var tq = -3000.SI<NewtonMeter>(); - var lookupOrig = gearboxDataOrig.Gears[7].LossMap.GetTorqueLoss(rpm, tq); - var lookupExt = gearboxDataExt.Gears[7].LossMap.GetTorqueLoss(rpm, tq); - - Assert.IsTrue(lookupOrig.Extrapolated); - Assert.IsFalse(lookupExt.Extrapolated); - - rpm = 1200.RPMtoRad(); - lookupOrig = gearboxDataOrig.Gears[7].LossMap.GetTorqueLoss(rpm, tq); - lookupExt = gearboxDataExt.Gears[7].LossMap.GetTorqueLoss(rpm, tq); - - Assert.IsTrue(lookupOrig.Extrapolated); - Assert.IsFalse(lookupExt.Extrapolated); - } - } } \ No newline at end of file diff --git a/VectoCore/VectoCoreTest/Utils/MockSimulationDataFactory.cs b/VectoCore/VectoCoreTest/Utils/MockSimulationDataFactory.cs index 4d4e0df9feefcf8381834804fbead9e8a6ea778d..dc782bc4e6cfd5e7cdb5a064f94d80d9a6d9a821 100644 --- a/VectoCore/VectoCoreTest/Utils/MockSimulationDataFactory.cs +++ b/VectoCore/VectoCoreTest/Utils/MockSimulationDataFactory.cs @@ -57,22 +57,26 @@ namespace TUGraz.VectoCore.Tests.Utils var dao = new DeclarationDataAdapter(); var engineData = dao.CreateEngineData(engineInput, null, gearboxInput, new List<ITorqueLimitInputData>()); return dao.CreateGearboxData(gearboxInput, engineData, ((IAxleGearInputData)gearboxInput).Ratio, 0.5.SI<Meter>(), - VehicleCategory.RigidTruck, - false); + VehicleCategory.RigidTruck); } else { var dao = new EngineeringDataAdapter(); var engineData = dao.CreateEngineData(engineInput, gearboxInput, new List<ITorqueLimitInputData>()); return dao.CreateGearboxData(gearboxInput, engineData, ((IAxleGearInputData)gearboxInput).Ratio, 0.5.SI<Meter>(), - VehicleCategory.RigidTruck, - true); + VehicleCategory.RigidTruck); } } - public static AxleGearData CreateAxleGearDataFromFile(string axleGearFile) + public static AxleGearData CreateAxleGearDataFromFile(string axleGearFile, bool declarationMode = true) { - var dao = new DeclarationDataAdapter(); - var axleGearInput = JSONInputDataFactory.ReadGearbox(axleGearFile); - return dao.CreateAxleGearData((IAxleGearInputData)axleGearInput, false); + if (declarationMode) { + var dao = new DeclarationDataAdapter(); + var axleGearInput = JSONInputDataFactory.ReadGearbox(axleGearFile); + return dao.CreateAxleGearData((IAxleGearInputData)axleGearInput); + } else { + var dao = new EngineeringDataAdapter(); + var axleGearInput = JSONInputDataFactory.ReadGearbox(axleGearFile); + return dao.CreateAxleGearData((IAxleGearInputData)axleGearInput); + } } public static CombustionEngineData CreateEngineDataFromFile(string engineFile, int numGears) diff --git a/VectoCore/VectoCoreTest/VectoCoreTest.csproj b/VectoCore/VectoCoreTest/VectoCoreTest.csproj index effacca291428601f1912ea0ea3153e697614230..97c3a4945043ac666c09b7083a46f24468b3c713 100644 --- a/VectoCore/VectoCoreTest/VectoCoreTest.csproj +++ b/VectoCore/VectoCoreTest/VectoCoreTest.csproj @@ -70,6 +70,7 @@ <Otherwise /> </Choose> <ItemGroup> + <Compile Include="Algorithms\MeanShiftClusteringTest.cs" /> <Compile Include="Dummy\EngineFLDTest.cs" /> <Compile Include="Exceptions\ExceptionTests.cs" /> <Compile Include="FileIO\JsonWriteTest.cs" /> @@ -175,7 +176,7 @@ <Compile Include="Utils\MockGearbox.cs" /> <Compile Include="Utils\ShiftPolygonDrawer.cs" /> <Compile Include="Utils\SITest.cs" /> - <Compile Include="Utils\DelauneyMapTest.cs" /> + <Compile Include="Algorithms\DelaunayMapTest.cs" /> <Compile Include="Utils\MockModalDataContainer.cs" /> <Compile Include="Utils\DoubleExtensionMethodTest.cs" /> <Compile Include="Utils\VectoMathTest.cs" />