From 6572597ee9ec4f346a7ee57bf52fbff4405c076c Mon Sep 17 00:00:00 2001 From: Markus Quaritsch <markus.quaritsch@tugraz.at> Date: Mon, 27 Feb 2017 17:03:18 +0100 Subject: [PATCH] extend sum conatiner, modal results to compute additional columns (time share per gear, etc.) --- .../OutputData/IModalDataContainer.cs | 138 +++++++++++++++--- .../OutputData/SummaryDataContainer.cs | 48 ++++-- 2 files changed, 154 insertions(+), 32 deletions(-) diff --git a/VectoCore/VectoCore/OutputData/IModalDataContainer.cs b/VectoCore/VectoCore/OutputData/IModalDataContainer.cs index 9e8ca6989c..d0e966be5d 100644 --- a/VectoCore/VectoCore/OutputData/IModalDataContainer.cs +++ b/VectoCore/VectoCore/OutputData/IModalDataContainer.cs @@ -33,8 +33,10 @@ using System; using System.Collections.Generic; using System.Data; using System.Linq; +using System.Runtime.Remoting.Metadata.W3cXsd2001; using TUGraz.VectoCommon.Utils; using TUGraz.VectoCore.Models.Simulation.Data; +using TUGraz.VectoCore.Models.Simulation.DataBus; using TUGraz.VectoCore.Models.Simulation.Impl; using TUGraz.VectoCore.Utils; @@ -96,14 +98,14 @@ namespace TUGraz.VectoCore.OutputData public static class ModalDataContainerExtensions { - public static SI Max(this IModalDataContainer data, ModalResultField field) + public static T Max<T>(this IModalDataContainer data, ModalResultField field) { - return data.GetValues<SI>(field).Max(); + return data.GetValues<T>(field).Max(); } - public static SI Min(this IModalDataContainer data, ModalResultField field) + public static T Min<T>(this IModalDataContainer data, ModalResultField field) { - return data.GetValues<SI>(field).Min(); + return data.GetValues<T>(field).Min(); } public static SI Average(this IEnumerable<SI> self, Func<SI, bool> filter) @@ -153,7 +155,7 @@ namespace TUGraz.VectoCore.OutputData a = x.Field<MeterPerSquareSecond>((int)ModalResultField.acc), dt = x.Field<Second>((int)ModalResultField.simulationInterval) }) - .Where(x => x.a > 0.125).Sum(x => x.dt).DefaultIfNull(0); + .Sum(x => x.a > 0.125 ? x.dt : 0.SI<Second>()).DefaultIfNull(0); return 100 * (accelerationTimeShare / data.Duration()).Cast<Scalar>(); } @@ -164,7 +166,7 @@ namespace TUGraz.VectoCore.OutputData a = x.Field<MeterPerSquareSecond>((int)ModalResultField.acc), dt = x.Field<Second>((int)ModalResultField.simulationInterval) }) - .Where(x => x.a < -0.125).Sum(x => x.dt).DefaultIfNull(0); + .Sum(x => x.a < -0.125 ? x.dt : 0.SI<Second>()).DefaultIfNull(0); return 100 * (decelerationTimeShare / data.Duration()).Cast<Scalar>(); } @@ -176,7 +178,7 @@ namespace TUGraz.VectoCore.OutputData a = x.Field<MeterPerSquareSecond>((int)ModalResultField.acc), dt = x.Field<Second>((int)ModalResultField.simulationInterval) }) - .Where(x => x.v >= 0.1 && x.a.IsBetween(-0.125, 0.125)).Sum(x => x.dt).DefaultIfNull(0); + .Sum(x => x.v >= 0.1 && x.a.IsBetween(-0.125, 0.125) ? x.dt : 0.SI<Second>()).DefaultIfNull(0); return 100 * (cruiseTime / data.Duration()).Cast<Scalar>(); } @@ -187,7 +189,7 @@ namespace TUGraz.VectoCore.OutputData v = x.Field<MeterPerSecond>((int)ModalResultField.v_act), dt = x.Field<Second>((int)ModalResultField.simulationInterval) }) - .Where(x => x.v < 0.1).Sum(x => x.dt) ?? 0.SI<Second>(); + .Sum(x => x.v < 0.1 ? x.dt : 0.SI<Second>()) ?? 0.SI<Second>(); return 100 * (stopTime / data.Duration()).Cast<Scalar>(); } @@ -263,9 +265,9 @@ namespace TUGraz.VectoCore.OutputData public static Meter Distance(this IModalDataContainer data) { - var max = data.Max(ModalResultField.dist); - var min = data.Min(ModalResultField.dist); - return max == null || min == null ? null : (max - min).Cast<Meter>(); + var max = data.Max<Meter>(ModalResultField.dist); + var min = data.Min<Meter>(ModalResultField.dist); + return max == null || min == null ? null : (max - min); } public static WattSecond WorkTotalMechanicalBrake(this IModalDataContainer data) @@ -299,15 +301,6 @@ namespace TUGraz.VectoCore.OutputData return data.TimeIntegral<WattSecond>(ModalResultField.P_air); } - public static WattSecond EngineWorkPositive(this IModalDataContainer data) - { - return data.TimeIntegral<WattSecond>(ModalResultField.P_eng_out, x => x > 0); - } - - public static WattSecond EngineWorkNegative(this IModalDataContainer data) - { - return data.TimeIntegral<WattSecond>(ModalResultField.P_eng_out, x => x < 0); - } public static WattSecond TotalEngineWorkPositive(this IModalDataContainer data) { @@ -414,7 +407,7 @@ namespace TUGraz.VectoCore.OutputData return data.TimeIntegral<Kilogram>(ModalResultField.FCMap) / distance; } - + public static Watt TotalPowerEnginePositiveAverage(this IModalDataContainer data) { var simulationIntervals = data.GetValues<Second>(ModalResultField.simulationInterval); @@ -450,6 +443,107 @@ namespace TUGraz.VectoCore.OutputData return sum; } - + + public static MeterPerSecond MaxSpeed(this ModalDataContainer data) + { + return data.Max<MeterPerSecond>(ModalResultField.v_act).DefaultIfNull(0); + } + + public static MeterPerSquareSecond MaxAcceleration(this ModalDataContainer data) + { + return data.Max<MeterPerSquareSecond>(ModalResultField.acc); + } + + public static MeterPerSquareSecond MaxDeceleration(this ModalDataContainer data) + { + return -data.Min<MeterPerSquareSecond>(ModalResultField.acc); + } + + public static PerSecond AvgEngineSpeed(this ModalDataContainer data) + { + var integral = data.Data.Rows.Cast<DataRow>() + .Sum(x => x.Field<PerSecond>((int)ModalResultField.n_eng_avg).Value() * + x.Field<Second>((int)ModalResultField.simulationInterval).Value()); + return (integral / Duration(data).Value()).SI<PerSecond>(); + } + + public static PerSecond MaxEngineSpeed(this IModalDataContainer data) + { + return data.Max<PerSecond>(ModalResultField.n_eng_avg); + } + + public static Scalar EngineMaxLoadTimeShare(this ModalDataContainer data) + { + var sum = data.Data.Rows.Cast<DataRow>() + .Select(x => new { + tMax = x.Field<NewtonMeter>((int)ModalResultField.Tq_full), + tEng = x.Field<NewtonMeter>((int)ModalResultField.T_eng_fcmap), + dt = x.Field<Second>((int)ModalResultField.simulationInterval) + }) + .Sum(x => x.tMax.IsEqual(x.tEng, 5.SI<NewtonMeter>()) ? x.dt : 0.SI<Second>()) ?? 0.SI<Second>(); + return 100 * sum / Duration(data); + } + + public static Scalar GearshiftCount(this ModalDataContainer data) + { + var prevGear = data.GetValues<uint>(ModalResultField.Gear).First(); + var gearCount = 0; + foreach (DataRow row in data.Data.Rows) { + var gear = row.Field<uint>((int)ModalResultField.Gear); + var speed = row.Field<MeterPerSecond>((int)ModalResultField.v_act); + if (speed.IsSmallerOrEqual(0.1)) { + prevGear = 0; + gearCount++; + continue; + } + if (gear == 0 || gear == prevGear) { + continue; + } + gearCount++; + prevGear = gear; + } + return gearCount.SI<Scalar>(); + } + + public static Scalar CoastingTimeShare(this ModalDataContainer data) + { + var sum = data.Data.Rows.Cast<DataRow>() + .Select(x => new { + DrivingBehavior = x.Field<DrivingBehavior>((int)ModalResultField.drivingBehavior), + dt = x.Field<Second>((int)ModalResultField.simulationInterval) + }) + .Sum(x => x.DrivingBehavior == DrivingBehavior.Coasting ? x.dt : 0.SI<Second>()) ?? 0.SI<Second>(); + return 100 * sum / Duration(data); + } + + public static Scalar BrakingTimeShare(this ModalDataContainer data) + { + var sum = data.Data.Rows.Cast<DataRow>() + .Select(x => new { + DrivingBehavior = x.Field<DrivingBehavior>((int)ModalResultField.drivingBehavior), + dt = x.Field<Second>((int)ModalResultField.simulationInterval) + }) + .Sum(x => x.DrivingBehavior == DrivingBehavior.Braking ? x.dt : 0.SI<Second>()) ?? 0.SI<Second>(); + return 100 * sum / Duration(data); + } + + public static Dictionary<uint, Scalar> TimeSharePerGear(this ModalDataContainer data, uint gearCount) + { + var retVal = new Dictionary<uint, Scalar>(); + for (uint i = 0; i <= gearCount; i++) { + retVal[i] = 0.SI<Scalar>(); + } + + foreach (var dataRow in data.Data.Rows.Cast<DataRow>()) { + var gear = dataRow.Field<uint>((int)ModalResultField.Gear); + retVal[gear] += dataRow.Field<Second>((int)ModalResultField.simulationInterval).Value(); + } + + var duration = Duration(data).Value(); + for (uint i = 0; i <= gearCount; i++) { + retVal[i] = 100 * retVal[i] / duration; + } + return retVal; + } } } \ No newline at end of file diff --git a/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs b/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs index 0a6c6a7367..f4f27c5f82 100644 --- a/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs +++ b/VectoCore/VectoCore/OutputData/SummaryDataContainer.cs @@ -33,6 +33,7 @@ using System; using System.Data; using System.Linq; using System.Runtime.CompilerServices; +using Org.BouncyCastle.Asn1; using TUGraz.VectoCommon.Models; using TUGraz.VectoCommon.Utils; using TUGraz.VectoCore.Configuration; @@ -42,7 +43,7 @@ using TUGraz.VectoCore.Configuration; namespace TUGraz.VectoCore.OutputData { public delegate void WriteSumData( - IModalDataContainer data, Kilogram vehicleMass, Kilogram loading, CubicMeter cargoVolume); + IModalDataContainer data, Kilogram vehicleMass, Kilogram loading, CubicMeter cargoVolume, uint gearCount); /// <summary> /// Class for the sum file in vecto. @@ -112,6 +113,19 @@ namespace TUGraz.VectoCore.OutputData public const string DEC_TIMESHARE = "DecelerationTimeShare [%]"; public const string CRUISE_TIMESHARE = "CruiseTimeShare [%]"; public const string STOP_TIMESHARE = "StopTimeShare [%]"; + + public const string MAX_SPEED = "max. speed [km/h"; + public const string MAX_ACCELERATION = "max. acc [m/s²]"; + public const string MAX_DECELERATION = "max. dec [m/s²]"; + public const string AVG_ENGINE_SPEED = "n_eng_avg [rpm]"; + public const string MAX_ENGINE_SPEED = "n_eng_max [rpm]"; + public const string NUM_GEARSHIFTS = "gear shifts [-]"; + public const string ENGINE_FULL_LOAD_TIME_SHARE = "Engine max. Load time share [%]"; + public const string COASTING_TIME_SHARE = "CoastingTimeShare [%]"; + public const string BRAKING_TIME_SHARE = "BrakingTImeShare [%]"; + + public const string TIME_SHARE_PER_GEAR_FORMAT = "Gear {0} TimeShare [%]"; + // ReSharper restore InconsistentNaming internal readonly DataTable _table; @@ -141,7 +155,9 @@ namespace TUGraz.VectoCore.OutputData P_WHEEL_POS, P_FCMAP_POS, E_FCMAP_POS, E_FCMAP_NEG, E_POWERTRAIN_INERTIA, E_AUX, E_CLUTCH_LOSS, E_TC_LOSS, E_SHIFT_LOSS, E_GBX_LOSS, E_RET_LOSS, E_ANGLE_LOSS, E_AXL_LOSS, E_BRAKE, E_VEHICLE_INERTIA, E_AIR, E_ROLL, E_GRAD, - ACC, ACC_POS, ACC_NEG, ACC_TIMESHARE, DEC_TIMESHARE, CRUISE_TIMESHARE, STOP_TIMESHARE + ACC, ACC_POS, ACC_NEG, ACC_TIMESHARE, DEC_TIMESHARE, CRUISE_TIMESHARE, STOP_TIMESHARE, + MAX_SPEED, MAX_ACCELERATION, MAX_DECELERATION, AVG_ENGINE_SPEED, MAX_ENGINE_SPEED, NUM_GEARSHIFTS, + ENGINE_FULL_LOAD_TIME_SHARE, COASTING_TIME_SHARE, BRAKING_TIME_SHARE }.Select(x => new DataColumn(x, typeof(SI))).ToArray()); } @@ -160,7 +176,7 @@ namespace TUGraz.VectoCore.OutputData /// </summary> [MethodImpl(MethodImplOptions.Synchronized)] public virtual void Write(IModalDataContainer modData, string jobFileName, string jobName, string cycleFileName, - Kilogram vehicleMass, Kilogram vehicleLoading, CubicMeter cargoVolume) + Kilogram vehicleMass, Kilogram vehicleLoading, CubicMeter cargoVolume, uint gearCount) { var row = _table.NewRow(); _table.Rows.Add(row); @@ -239,11 +255,6 @@ namespace TUGraz.VectoCore.OutputData } row[P_WHEEL_POS] = modData.PowerWheelPositive().ConvertTo().Kilo.Watt; - //row[P_BRAKE_LOSS] = modData.PowerBrake().ConvertTo().Kilo.Watt; - //row[P_ANGLE_LOSS] = modData.PowerAngle().ConvertTo().Kilo.Watt; - //row[P_TC_LOSS] = modData.PowerTorqueConverter().ConvertTo().Kilo.Watt; - //row[P_CLUTCH_POS] = modData.EnginePowerPositiveAverage().ConvertTo().Kilo.Watt; - //row[P_CLUTCH_NEG] = modData.EnginePowerNegativeAverage().ConvertTo().Kilo.Watt; row[P_FCMAP_POS] = modData.TotalPowerEnginePositiveAverage().ConvertTo().Kilo.Watt; @@ -264,8 +275,6 @@ namespace TUGraz.VectoCore.OutputData row[colName] = modData.AuxiliaryWork(aux.Value).ConvertTo().Kilo.Watt.Hour; } - //row[E_CLUTCH_POS] = modData.EngineWorkPositive().ConvertTo().Kilo.Watt.Hour; - //row[E_CLUTCH_NEG] = modData.EngineWorkNegative().ConvertTo().Kilo.Watt.Hour; row[E_FCMAP_POS] = modData.TotalEngineWorkPositive().ConvertTo().Kilo.Watt.Hour; row[E_FCMAP_NEG] = -modData.TotalEngineWorkNegative().ConvertTo().Kilo.Watt.Hour; row[E_POWERTRAIN_INERTIA] = modData.PowerAccelerations().ConvertTo().Kilo.Watt.Hour; @@ -303,6 +312,25 @@ namespace TUGraz.VectoCore.OutputData var stopTimeShare = modal.StopTimeShare(); row[STOP_TIMESHARE] = stopTimeShare; + row[MAX_SPEED] = modal.MaxSpeed().AsKmph.SI<Scalar>(); + row[MAX_ACCELERATION] = modal.MaxAcceleration(); + row[MAX_DECELERATION] = modal.MaxDeceleration(); + row[AVG_ENGINE_SPEED] = modal.AvgEngineSpeed().AsRPM.SI<Scalar>(); + row[MAX_ENGINE_SPEED] = modData.MaxEngineSpeed().AsRPM.SI<Scalar>(); + row[NUM_GEARSHIFTS] = modal.GearshiftCount(); + row[ENGINE_FULL_LOAD_TIME_SHARE] = modal.EngineMaxLoadTimeShare(); + row[COASTING_TIME_SHARE] = modal.CoastingTimeShare(); + row[BRAKING_TIME_SHARE] = modal.BrakingTimeShare(); + + var timeSharePerGear = modal.TimeSharePerGear(gearCount); + + for (uint i = 0; i <= gearCount; i++) { + var colName = string.Format(TIME_SHARE_PER_GEAR_FORMAT, i); + if (!_table.Columns.Contains(colName)) { + _table.Columns.Add(colName, typeof(SI)); + } + row[colName] = timeSharePerGear[i]; + } if (accTimeShare != null && decTimeShare != null && cruiseTimeShare != null) { var shareSum = accTimeShare + decTimeShare + cruiseTimeShare + stopTimeShare; if (!shareSum.IsEqual(100)) { -- GitLab