diff --git a/VECTO.sln.DotSettings b/VECTO.sln.DotSettings index 519ebe2c3f9db225ac68a45e912e6e7854fe41ad..31f403d6de965a22dd23f2c7dfb5f0c2c2e02e2e 100644 --- a/VECTO.sln.DotSettings +++ b/VECTO.sln.DotSettings @@ -24,6 +24,7 @@ <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=PT/@EntryIndexedValue">PT</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RP/@EntryIndexedValue">RP</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SI/@EntryIndexedValue">SI</s:String> + <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=WHTC/@EntryIndexedValue">WHTC</s:String> <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FCONSTANT/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FVARIABLE/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></s:String> <s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FCONSTRUCTOR/@EntryIndexedValue"><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></s:String> diff --git a/VectoCore/Models/Declaration/DeclarationData.cs b/VectoCore/Models/Declaration/DeclarationData.cs index 9646e461840383fb41b19a72cf3ebe3ade091974..4bb5d7f3b6bb2106fb71b5f8f6857ee4aae8d711 100644 --- a/VectoCore/Models/Declaration/DeclarationData.cs +++ b/VectoCore/Models/Declaration/DeclarationData.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.Data; +using System.Linq; using TUGraz.VectoCore.Models.SimulationComponent.Data; using TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox; using TUGraz.VectoCore.Models.SimulationComponent.Impl; @@ -20,6 +22,7 @@ namespace TUGraz.VectoCore.Models.Declaration private PneumaticSystem _pneumaticSystem; private SteeringPump _steeringPump; private WHTCCorrection _whtcCorrection; + private AirDrag _airDrag; public static Wheels Wheels { @@ -85,6 +88,11 @@ namespace TUGraz.VectoCore.Models.Declaration get { return Instance()._whtcCorrection ?? (Instance()._whtcCorrection = new WHTCCorrection()); } } + public static AirDrag AirDrag + { + get { return Instance()._airDrag ?? (Instance()._airDrag = new AirDrag()); } + } + public static int PoweredAxle() { return 1; @@ -214,4 +222,75 @@ namespace TUGraz.VectoCore.Models.Declaration } } } + + internal class AirDrag : LookupData<VehicleCategory, double> + { + private const string ResourceId = "TUGraz.VectoCore.Resources.Declaration.VCDV.parameters.csv"; + + public AirDrag() + { + ParseData(ReadCsvResource(ResourceId)); + } + + + protected override void ParseData(DataTable table) + { + // todo: constant!! + var vWind = 3.SI().Kilo.Meter.Per.Hour.Cast<MeterPerSecond>(); + + // todo: get from vehicle or move whole procedure to vehicle + var cdA0Actual = 0; + + Data.Clear(); + foreach (DataRow row in table.Rows) { + var cat = row.Field<string>("Parameters"); + var values = new { a1 = row.ParseDouble("a1"), a2 = row.ParseDouble("a2"), a3 = row.ParseDouble("a3") }; + + var betas = new List<double>(); + var deltaCdAs = new List<double>(); + for (var beta = 0; beta <= 12; beta++) { + betas.Add(beta); + var deltaCdA = values.a1 * beta + values.a2 * beta * beta + values.a3 * beta * beta * beta; + deltaCdAs.Add(deltaCdA); + } + + var cdX = new List<double> { 0 }; + var cdY = new List<double> { 0 }; + + for (var vVeh = 60; vVeh <= 100; vVeh += 5) { + var cdASum = 0.0; + for (var alpha = 0; alpha <= 180; alpha += 10) { + var vWindX = vWind * Math.Cos(alpha * Math.PI / 180); + var vWindY = vWind * Math.Sin(alpha * Math.PI / 180); + var vAirX = vVeh + vWindX; + var vAirY = vWindY; + var vAir = VectoMath.Sqrt<MeterPerSecond>(vAirX * vAirX + vAirY * vAirY); + var beta = Math.Atan((vAirY / vAirX).Double()) * 180 / Math.PI; + + var k = 1; + if (betas.First() < beta) { + k = 0; + while (betas[k] < beta && k < betas.Count) { + k++; + } + } + + var deltaCdA = VectoMath.Interpolate(betas[k - 1], betas[k], deltaCdAs[k - 1], deltaCdAs[k], beta); + + var cdA = cdA0Actual + deltaCdA; + + var share = 10 / 180; + if (vVeh == 0 || vVeh == 180) { + share /= 2; + } + cdASum += share * cdA * (vAir * vAir / (vVeh * vVeh)).Double(); + } + cdX.Add(vVeh); + cdY.Add(cdASum); + } + + cdY[0] = cdY[1]; + } + } + } } \ No newline at end of file diff --git a/VectoCore/Utils/SI.cs b/VectoCore/Utils/SI.cs index b5e21f5c96720378b4a1c8b7357dc1c0562747f5..f68ab8817d6341ef8ff11fe1d3faf0a1c68b30c2 100644 --- a/VectoCore/Utils/SI.cs +++ b/VectoCore/Utils/SI.cs @@ -15,7 +15,7 @@ namespace TUGraz.VectoCore.Utils { static Newton() { - Constructors.Add(typeof (Newton), val => new Newton(val)); + Constructors.Add(typeof(Newton), val => new Newton(val)); } [JsonConstructor] @@ -31,7 +31,7 @@ namespace TUGraz.VectoCore.Utils { static Radian() { - Constructors.Add(typeof (Radian), val => new Radian(val)); + Constructors.Add(typeof(Radian), val => new Radian(val)); } [JsonConstructor] @@ -43,7 +43,7 @@ namespace TUGraz.VectoCore.Utils { static MeterPerSquareSecond() { - Constructors.Add(typeof (MeterPerSquareSecond), val => new MeterPerSquareSecond(val)); + Constructors.Add(typeof(MeterPerSquareSecond), val => new MeterPerSquareSecond(val)); } protected MeterPerSquareSecond(double val) : base(new SI(val).Meter.Per.Square.Second) {} @@ -53,7 +53,7 @@ namespace TUGraz.VectoCore.Utils { static Second() { - Constructors.Add(typeof (Second), val => new Second(val)); + Constructors.Add(typeof(Second), val => new Second(val)); } [JsonConstructor] @@ -64,7 +64,7 @@ namespace TUGraz.VectoCore.Utils { static Meter() { - Constructors.Add(typeof (Meter), val => new Meter(val)); + Constructors.Add(typeof(Meter), val => new Meter(val)); } protected Meter(double val) : base(new SI(val).Meter) {} @@ -74,7 +74,7 @@ namespace TUGraz.VectoCore.Utils { static Ton() { - Constructors.Add(typeof (Ton), val => new Ton(val)); + Constructors.Add(typeof(Ton), val => new Ton(val)); } [JsonConstructor] @@ -86,7 +86,7 @@ namespace TUGraz.VectoCore.Utils { static Kilogram() { - Constructors.Add(typeof (Kilogram), val => new Kilogram(val)); + Constructors.Add(typeof(Kilogram), val => new Kilogram(val)); } [JsonConstructor] @@ -97,7 +97,7 @@ namespace TUGraz.VectoCore.Utils { static SquareMeter() { - Constructors.Add(typeof (SquareMeter), val => new SquareMeter(val)); + Constructors.Add(typeof(SquareMeter), val => new SquareMeter(val)); } [JsonConstructor] @@ -108,7 +108,7 @@ namespace TUGraz.VectoCore.Utils { static CubicMeter() { - Constructors.Add(typeof (CubicMeter), val => new CubicMeter(val)); + Constructors.Add(typeof(CubicMeter), val => new CubicMeter(val)); } [JsonConstructor] @@ -119,7 +119,7 @@ namespace TUGraz.VectoCore.Utils { static KilogramSquareMeter() { - Constructors.Add(typeof (KilogramSquareMeter), val => new KilogramSquareMeter(val)); + Constructors.Add(typeof(KilogramSquareMeter), val => new KilogramSquareMeter(val)); } [JsonConstructor] @@ -130,7 +130,7 @@ namespace TUGraz.VectoCore.Utils { static KilogramPerWattSecond() { - Constructors.Add(typeof (KilogramPerWattSecond), val => new KilogramPerWattSecond(val)); + Constructors.Add(typeof(KilogramPerWattSecond), val => new KilogramPerWattSecond(val)); } [JsonConstructor] @@ -141,7 +141,7 @@ namespace TUGraz.VectoCore.Utils { static Watt() { - Constructors.Add(typeof (Watt), val => new Watt(val)); + Constructors.Add(typeof(Watt), val => new Watt(val)); } [JsonConstructor] @@ -162,7 +162,7 @@ namespace TUGraz.VectoCore.Utils { static PerSecond() { - Constructors.Add(typeof (PerSecond), val => new PerSecond(val)); + Constructors.Add(typeof(PerSecond), val => new PerSecond(val)); } [JsonConstructor] @@ -173,7 +173,7 @@ namespace TUGraz.VectoCore.Utils { static MeterPerSecond() { - Constructors.Add(typeof (MeterPerSecond), val => new MeterPerSecond(val)); + Constructors.Add(typeof(MeterPerSecond), val => new MeterPerSecond(val)); } [JsonConstructor] @@ -191,7 +191,7 @@ namespace TUGraz.VectoCore.Utils { static RoundsPerMinute() { - Constructors.Add(typeof (RoundsPerMinute), val => new RoundsPerMinute(val)); + Constructors.Add(typeof(RoundsPerMinute), val => new RoundsPerMinute(val)); } [JsonConstructor] @@ -203,7 +203,7 @@ namespace TUGraz.VectoCore.Utils { static NewtonMeter() { - Constructors.Add(typeof (NewtonMeter), val => new NewtonMeter(val)); + Constructors.Add(typeof(NewtonMeter), val => new NewtonMeter(val)); } [JsonConstructor] @@ -237,8 +237,8 @@ namespace TUGraz.VectoCore.Utils public static T Create(double val) { - RuntimeHelpers.RunClassConstructor(typeof (T).TypeHandle); - return Constructors[typeof (T)](val); + RuntimeHelpers.RunClassConstructor(typeof(T).TypeHandle); + return Constructors[typeof(T)](val); } protected SIBase(Type type, Func<double, T> constructor) @@ -553,6 +553,19 @@ namespace TUGraz.VectoCore.Utils return new SI(Math.Abs(Val), this); } + /// <summary> + /// Returns the absolute value. + /// </summary> + public SI Sqrt() + { + var si = ToBasicUnits(); + var numerator = si.Numerator.Where((u, i) => i % 2 == 0); + var denominator = si.Denominator.Where((u, i) => i % 2 == 0); + var root = new SI(Math.Sqrt(si.Val), numerator, denominator); + Contract.Requires(root * root == this); + return root; + } + #region Unit Definitions /// <summary> diff --git a/VectoCore/Utils/VectoMath.cs b/VectoCore/Utils/VectoMath.cs index 09a9a33de195a3761a0f2202047a9430d692726b..ae853e3781282565e21c61be7d77f84c95676126 100644 --- a/VectoCore/Utils/VectoMath.cs +++ b/VectoCore/Utils/VectoMath.cs @@ -24,6 +24,15 @@ namespace TUGraz.VectoCore.Utils return ((xint - x1) * (y2 - y1) / (x2 - x1) + y1).Cast<TResult>(); } + /// <summary> + /// Linearly interpolates a value between two points. + /// </summary> + public static double Interpolate(double x1, double x2, double y1, double y2, double xint) + { + return ((xint - x1) * (y2 - y1) / (x2 - x1) + y1); + } + + /// <summary> /// Returns the absolute value. /// </summary> @@ -55,5 +64,10 @@ namespace TUGraz.VectoCore.Utils { return c1.CompareTo(c2) >= 0 ? c1 : c2; } + + public static T Sqrt<T>(SI si) where T : SIBase<T> + { + si.Sqrt().Cast<T>(); + } } } \ No newline at end of file diff --git a/VectoCoreTest/Models/Declaration/DeclarationDataTest.cs b/VectoCoreTest/Models/Declaration/DeclarationDataTest.cs index 0746408bb17635e79df70eb433687e42cb2fb7ee..3e525cdb9c4418bce877b69c2b3e209a09698593 100644 --- a/VectoCoreTest/Models/Declaration/DeclarationDataTest.cs +++ b/VectoCoreTest/Models/Declaration/DeclarationDataTest.cs @@ -97,8 +97,19 @@ namespace TUGraz.VectoCore.Tests.Models.Declaration } [TestMethod] - public void VCDVTest() + public void AirDragTest() { + var airDrag = DeclarationData.AirDrag; + + //declaration + var Categories = Enum.GetValues(typeof(VehicleCategory)).Cast<VehicleCategory>().ToArray(); + + //todo: insert real test values + var expectedForCategory = new[] { 0, 0, 0, 0, 0 }; + for (var i = 0; i < Categories.Length; i++) { + Assert.AreEqual(expectedForCategory[i], airDrag.Lookup(Categories[i])); + } + Assert.Inconclusive(); }