Code development platform for open source projects from the European Union institutions :large_blue_circle: EU Login authentication by SMS has been phased out. To see alternatives please check here

Skip to content
Snippets Groups Projects
Commit eca85696 authored by Michael KRISPER's avatar Michael KRISPER
Browse files

Merge branch 'feature/VECTO-105-SimulationDataFactory' into...

Merge branch 'feature/VECTO-105-SimulationDataFactory' into feature/VECTO-102-auxiliaries-identification

Conflicts:
	VectoCore/VectoCore.csproj
	VectoCoreTest/Models/Declaration/DeclarationDataTest.cs
parents d09ad3d1 e0141e6b
Branches
Tags
No related merge requests found
Showing
with 575 additions and 1861 deletions
#!/usr/bin/env python
"""
1) Copies the declaration files into the project resource directory.
2) Renames the mission files accordingly
3) Scales Pneumatic System from KW to W.
4) Renames the VCDV paramerters.csv to parameters.csv
5) Scales the WHTC-Weighting percentage values from 0-100 to 0-1
Prerequisites:
* Original declaration files accessible in "root/Declaration"
Usage:
python DeclarationConverter.py
"""
import os
import shutil
__author__ = "Michael Krisper"
__email__ = "michael.krisper@tugraz.at"
__date__ = "2015-07-15"
__version__ = "1.0.0"
SOURCE = "../Declaration"
DESTINATION = os.path.abspath("../VectoCore/Resources/Declaration")
def main(source_path, destination_path):
# Copy files from source to resource dir
shutil.rmtree(destination_path, onerror=lambda dir, path, err: print(dir, path, err))
shutil.copytree(source_path, destination_path, ignore=lambda src, names: names if "Reports" in src else [])
# Rename mission cycles
os.chdir(os.path.join(destination_path, "MissionCycles"))
for file in os.listdir():
os.rename(file, file.replace("_", "").replace(" ", "").replace("Citybus", "").replace("Bus", ""))
# Adjust PS table
os.chdir(os.path.join(destination_path, "VAUX"))
with open("PS-Table.csv", "r") as f:
lines = f.readlines()
with open("PS-Table.csv", "w") as f:
f.write(lines[0])
for line in lines[1:]:
values = line.split(",")
f.write("{},{}\n".format(values[0], ",".join(str(float(v)*1000) for v in values[1:])))
#VCDV
os.chdir(os.path.join(destination_path, "VCDV"))
os.rename("paramerters.csv", "parameters.csv")
# WHTC Weighting Factors
os.chdir(os.path.join(destination_path))
with open("WHTC-Weighting-Factors.csv", "r") as f:
lines = f.readlines()
with open("WHTC-Weighting-Factors.csv", "w") as f:
f.write(lines[0])
for line in lines[1:]:
values = line.split(",")
f.write("{},{}\n".format(values[0], ",".join(str(float(v) / 100) for v in values[1:])))
if __name__ == "__main__":
main(SOURCE, DESTINATION)
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>e23b3a9b-62e7-4476-849e-eef1c3804a2f</ProjectGuid>
<ProjectHome>.</ProjectHome>
<StartupFile>DeclarationConverter.py</StartupFile>
<SearchPath>
</SearchPath>
<WorkingDirectory>.</WorkingDirectory>
<OutputPath>.</OutputPath>
<Name>DeclarationConverter</Name>
<RootNamespace>DeclarationConverter</RootNamespace>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DebugSymbols>true</DebugSymbols>
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
</PropertyGroup>
<ItemGroup>
<Compile Include="DeclarationConverter.py" />
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<PtvsTargetsFile>$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Python Tools\Microsoft.PythonTools.targets</PtvsTargetsFile>
</PropertyGroup>
<Import Condition="Exists($(PtvsTargetsFile))" Project="$(PtvsTargetsFile)" />
<Import Condition="!Exists($(PtvsTargetsFile))" Project="$(MSBuildToolsPath)\Microsoft.Common.targets" />
<!-- Uncomment the CoreCompile target to enable the Build command in
Visual Studio and specify your pre- and post-build commands in
the BeforeBuild and AfterBuild targets below. -->
<!--<Target Name="CoreCompile" />-->
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
</Project>
\ No newline at end of file
......@@ -11,6 +11,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VectoCore", "VectoCore\Vect
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VectoCoreTest", "VectoCoreTest\VectoCoreTest.csproj", "{6A27F93E-4A58-48F6-B00B-3908C5D3D5A2}"
EndProject
Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "DeclarationConverter", "DeclarationConverter\DeclarationConverter.pyproj", "{E23B3A9B-62E7-4476-849E-EEF1C3804A2F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
......@@ -55,6 +57,12 @@ Global
{6A27F93E-4A58-48F6-B00B-3908C5D3D5A2}.Release|Any CPU.Build.0 = Release|Any CPU
{6A27F93E-4A58-48F6-B00B-3908C5D3D5A2}.Release|x64.ActiveCfg = Release|Any CPU
{6A27F93E-4A58-48F6-B00B-3908C5D3D5A2}.Release|x86.ActiveCfg = Release|Any CPU
{E23B3A9B-62E7-4476-849E-EEF1C3804A2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E23B3A9B-62E7-4476-849E-EEF1C3804A2F}.Debug|x64.ActiveCfg = Debug|Any CPU
{E23B3A9B-62E7-4476-849E-EEF1C3804A2F}.Debug|x86.ActiveCfg = Debug|Any CPU
{E23B3A9B-62E7-4476-849E-EEF1C3804A2F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E23B3A9B-62E7-4476-849E-EEF1C3804A2F}.Release|x64.ActiveCfg = Release|Any CPU
{E23B3A9B-62E7-4476-849E-EEF1C3804A2F}.Release|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
......
......@@ -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">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FBLOCK_005FSCOPE_005FVARIABLE/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/JavaScriptNaming/UserRules/=JS_005FCONSTRUCTOR/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
......
using System;
using System.Data;
using System.Linq;
using TUGraz.VectoCore.Utils;
namespace TUGraz.VectoCore.Models.Declaration
{
public class AirDrag : LookupData<string, AirDrag.AirDragEntry>
{
protected const string ResourceId = "TUGraz.VectoCore.Resources.Declaration.VCDV.parameters.csv";
public AirDrag()
{
ParseData(ReadCsvResource(ResourceId));
}
protected override void ParseData(DataTable table)
{
Data = table.Rows.Cast<DataRow>().ToDictionary(row => row.Field<string>("Parameters"), row => new AirDragEntry {
A1 = row.ParseDouble("a1"),
A2 = row.ParseDouble("a2"),
A3 = row.ParseDouble("a3")
});
}
public AirDragEntry Lookup(VehicleCategory category)
{
switch (category) {
case VehicleCategory.CityBus:
case VehicleCategory.InterurbanBus:
case VehicleCategory.Coach:
return Lookup("CoachBus");
case VehicleCategory.Tractor:
return Lookup("TractorSemitrailer");
case VehicleCategory.RigidTruck:
return Lookup("RigidSolo");
default:
throw new ArgumentOutOfRangeException("category", category, null);
}
}
public class AirDragEntry
{
public double A1 { get; set; }
public double A2 { get; set; }
public double A3 { get; set; }
protected bool Equals(AirDragEntry other)
{
return A1.Equals(other.A1) && A2.Equals(other.A2) && A3.Equals(other.A3);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) {
return false;
}
if (ReferenceEquals(this, obj)) {
return true;
}
if (obj.GetType() != this.GetType()) {
return false;
}
return Equals((AirDragEntry)obj);
}
public override int GetHashCode()
{
unchecked {
var hashCode = A1.GetHashCode();
hashCode = (hashCode * 397) ^ A2.GetHashCode();
hashCode = (hashCode * 397) ^ A3.GetHashCode();
return hashCode;
}
}
}
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Data;
using NLog.Targets.Wrappers;
using TUGraz.VectoCore.Models.SimulationComponent.Data;
using TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox;
using TUGraz.VectoCore.Models.SimulationComponent.Impl;
......@@ -20,6 +22,8 @@ namespace TUGraz.VectoCore.Models.Declaration
private PneumaticSystem _pneumaticSystem;
private SteeringPump _steeringPump;
private WHTCCorrection _whtcCorrection;
private AirDrag _airDrag;
private TorqueConverter _torqueConverter;
public static Wheels Wheels
{
......@@ -85,6 +89,16 @@ 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 TorqueConverter TorqueConverter
{
get { return Instance()._torqueConverter ?? (Instance()._torqueConverter = new TorqueConverter()); }
}
public static int PoweredAxle()
{
return 1;
......@@ -214,4 +228,65 @@ namespace TUGraz.VectoCore.Models.Declaration
}
}
}
public class TorqueConverter : LookupData<double, TorqueConverter.TorqueConverterEntry>
{
protected const string resourceID = "TUGraz.VectoCore.Resources.Declaration.DefaultTC.vtcc";
public TorqueConverter()
{
ParseData(ReadCsvResource(resourceID));
}
[Obsolete("Default Lookup not availabel. Use LookupMu or LookupTorque instead.", true)]
protected new TorqueConverterEntry Lookup(double key)
{
throw new InvalidOperationException(
"Default Lookup not available. Use TorqueConverter.LookupMu() or TorqueConverter.LookupTorque() instead.");
}
public NewtonMeter LookupTorque(double nu, PerSecond angularSpeedIn, PerSecond referenceSpeed)
{
var sec = Data.GetSection(kv => kv.Key < nu);
if (nu < sec.Item1.Key || sec.Item2.Key < nu) {
Log.Warn(string.Format("TCextrapol: nu = {0} [n_out/n_in]", nu));
}
var torque = VectoMath.Interpolate(sec.Item1.Key, sec.Item2.Key, sec.Item1.Value.Torque, sec.Item2.Value.Torque, nu);
return torque * Math.Pow((angularSpeedIn / referenceSpeed).Scalar(), 2);
}
public double LookupMu(double nu)
{
var sec = Data.GetSection(kv => kv.Key < nu);
if (nu < sec.Item1.Key || sec.Item2.Key < nu) {
Log.Warn(string.Format("TCextrapol: nu = {0} [n_out/n_in]", nu));
}
return VectoMath.Interpolate(sec.Item1.Key, sec.Item2.Key, sec.Item1.Value.Mu, sec.Item2.Value.Mu, nu);
}
protected override void ParseData(DataTable table)
{
Data.Clear();
foreach (DataRow row in table.Rows) {
Data[row.ParseDouble("nue")] = new TorqueConverterEntry {
Mu = row.ParseDouble("mue"),
Torque = row.ParseDouble("MP1000 (1000/rpm)^2*Nm").SI<NewtonMeter>()
};
}
}
public class TorqueConverterEntry
{
public double Mu { get; set; }
public NewtonMeter Torque { get; set; }
}
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection;
using Common.Logging;
using TUGraz.VectoCore.Utils;
......@@ -12,24 +11,15 @@ namespace TUGraz.VectoCore.Models.Declaration
protected LookupData()
{
Log = LogManager.GetLogger(GetType());
//var csvFile = ReadCsvResource(ResourceId);
//ParseData(csvFile);
//ParseData(ReadData());
}
[NonSerialized] protected ILog Log;
//protected abstract string ResourceId { get; }
//protected abstract DataTable ReadData();
protected abstract void ParseData(DataTable table);
protected DataTable ReadCsvResource(string resourceId)
{
var myAssembly = Assembly.GetExecutingAssembly();
var file = myAssembly.GetManifestResourceStream(resourceId);
return VectoCSVFile.ReadStream(file);
return VectoCSVFile.ReadStream(RessourceHelper.ReadStream(resourceId));
}
protected DataTable ReadCsvFile(string fileName)
......
using System;
using System.Collections.Generic;
using TUGraz.VectoCore.Exceptions;
using TUGraz.VectoCore.FileIO;
using TUGraz.VectoCore.FileIO.DeclarationFile;
using TUGraz.VectoCore.Models.Declaration;
using TUGraz.VectoCore.Utils;
......@@ -69,8 +67,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data
public SquareMeter CrossSectionAreaRigidTruck { get; internal set; }
public CrossWindCorrectionMode CrossWindCorrection { get; internal set; }
public Meter DynamicTyreRadius { get; internal set; }
public Kilogram ReducedMassWheels { get; private set; }
......
......@@ -58,7 +58,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
// TODO!!
var dx = 0.SI<Meter>();
return _outPort.Request(absTime, dx, Data.Entries[index].VehicleTargetSpeed,
return _outPort.Request(absTime, dt, Data.Entries[index].VehicleTargetSpeed,
Data.Entries[index].RoadGradient);
}
......
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using TUGraz.VectoCore.Configuration;
using TUGraz.VectoCore.Models.Connector.Ports;
using TUGraz.VectoCore.Models.Declaration;
using TUGraz.VectoCore.Models.Simulation.Data;
using TUGraz.VectoCore.Models.Simulation.Impl;
using TUGraz.VectoCore.Models.SimulationComponent.Data;
......@@ -72,18 +78,92 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
protected Newton AirDragResistance()
{
// TODO different types of cross-wind correction...
var vAir = _currentState.Velocity;
var Cd = _data.DragCoefficient;
switch (_data.CrossWindCorrection) {
// todo: different CdA in different file versions!
var CdA = _data.CrossSectionArea * _data.DragCoefficient;
switch (_data.CrossWindCorrectionMode) {
case CrossWindCorrectionMode.NoCorrection:
break;
case CrossWindCorrectionMode.SpeedDependent:
//Cd =
var values = DeclarationData.AirDrag.Lookup(_data.VehicleCategory);
var curve = CalculateAirResistanceCurve(values);
CdA *= AirDragInterpolate(curve, _currentState.Velocity);
break;
// todo ask raphael: What is the air cd decl mode?
//case tCdMode.CdOfVdecl
// CdA = AirDragInterpolate(curve, _currentState.Velocity);
// break;
case CrossWindCorrectionMode.VAirBeta:
break;
//todo: get data from driving cycle
//vAir = DrivingCycleData.DrivingCycleEntry.AirSpeedRelativeToVehicle;
//CdA *= AirDragInterpolate(Math.Abs(DrivingCycleData.DrivingCycleEntry.WindYawAngle))
throw new NotImplementedException("VAirBeta is not implemented");
//break;
}
return (CdA * Physics.AirDensity / 2 * vAir * vAir).Cast<Newton>();
}
private double AirDragInterpolate(IEnumerable<Point> curve, MeterPerSecond x)
{
var p = curve.GetSection(c => c.X < x);
if (x < p.Item1.X || p.Item2.X < x) {
Log.Error(_data.CrossWindCorrectionMode == CrossWindCorrectionMode.VAirBeta
? string.Format("CdExtrapol β = {0}", x)
: string.Format("CdExtrapol v = {0}", x));
}
return VectoMath.Interpolate(p.Item1.X, p.Item2.X, p.Item1.Y, p.Item2.Y, x);
}
public class Point
{
public MeterPerSecond X;
public double Y;
}
protected Point[] CalculateAirResistanceCurve(AirDrag.AirDragEntry values)
{
// todo: get from vehicle or move whole procedure to vehicle
var cdA0Actual = 0;
var betaValues = new Dictionary<int, double>();
for (var beta = 0; beta <= 12; beta++) {
var deltaCdA = values.A1 * beta + values.A2 * beta * beta + values.A3 * beta * beta * beta;
betaValues[beta] = deltaCdA;
}
var points = new List<Point> { new Point { X = 0.SI<MeterPerSecond>(), Y = 0 } };
for (var vVeh = 60; vVeh <= 100; vVeh += 5) {
var cdASum = 0.0;
for (var alpha = 0; alpha <= 180; alpha += 10) {
var vWindX = Physics.BaseWindSpeed * Math.Cos(alpha.ToRadian());
var vWindY = Physics.BaseWindSpeed * Math.Sin(alpha.ToRadian());
var vAirX = vVeh + vWindX;
var vAirY = vWindY;
var vAir = VectoMath.Sqrt<MeterPerSecond>(vAirX * vAirX + vAirY * vAirY);
var beta = Math.Atan((vAirY / vAirX).Value()).ToDegree();
var sec = betaValues.GetSection(b => b.Key < beta);
var deltaCdA = VectoMath.Interpolate(sec.Item1.Key, sec.Item2.Key, sec.Item1.Value, sec.Item2.Value, beta);
var cdA = cdA0Actual + deltaCdA;
var degreeShare = ((vVeh != 0 && vVeh != 180) ? 10.0 / 180.0 : 5.0 / 180.0);
cdASum += degreeShare * cdA * (vAir * vAir / (vVeh * vVeh)).Scalar();
}
points.Add(new Point { X = vVeh.SI<MeterPerSecond>(), Y = cdASum });
}
return (Cd * _data.CrossSectionArea * Physics.AirDensity / 2 * vAir * vAir).Cast<Newton>();
points[0].Y = points[1].Y;
return points.ToArray();
}
protected Newton DriverAcceleration(MeterPerSquareSecond accelleration)
......
This diff is collapsed.
......@@ -95,6 +95,16 @@ namespace TUGraz.VectoCore.Utils
return self.SI().Rounds.Per.Minute.ConvertTo().Radian.Per.Second.Cast<PerSecond>();
}
public static double ToRadian(this double self)
{
return self * Math.PI / 180.0;
}
public static double ToDegree(this double self)
{
return self * 180.0 / Math.PI;
}
/// <summary>
/// Creates an SI object for the number (unit-less: [-]).
/// </summary>
......
using System;
using System.Collections.Generic;
using System.Linq;
......@@ -9,5 +10,34 @@ namespace TUGraz.VectoCore.Utils
{
return self.Select(StringExtensionMethods.ToDouble);
}
public static Func<bool> Once()
{
var once = 0;
return () => once++ == 0;
}
/// <summary>
/// Get the two adjacent items where the predicate is true.
/// If the predicate never gets true, the last 2 elements are returned.
/// </summary>
public static Tuple<T, T> GetSection<T>(this IEnumerable<T> self, Func<T, bool> skip, out int index)
{
var list = self.ToList();
var skipList = list.Select((arg1, i) => new { skip = skip(arg1) && i < list.Count - 1, i, value = arg1 });
var p = skipList.SkipWhile(x => x.skip).First();
index = Math.Max(p.i - 1, 0);
return Tuple.Create(list[index], list[index + 1]);
}
/// <summary>
/// Get the two adjacent items where the predicate is true.
/// If the predicate never gets true, the last 2 elements are returned.
/// </summary>
public static Tuple<T, T> GetSection<T>(this IEnumerable<T> self, Func<T, bool> predicate)
{
int unused;
return self.GetSection(predicate, out unused);
}
}
}
\ No newline at end of file
using System;
namespace TUGraz.VectoCore.Utils
{
public static class IntExtensionMethods
......@@ -32,6 +34,11 @@ namespace TUGraz.VectoCore.Utils
return SIBase<T>.Create(d);
}
public static double ToRadian(this int self)
{
return self * Math.PI / 180.0;
}
/// <summary>
/// Modulo functions which also works on negative Numbers (not like the built-in %-operator which just returns the remainder).
/// </summary>
......
......@@ -7,5 +7,7 @@
public static readonly SI AirDensity = 1.188.SI().Kilo.Gramm.Per.Cubic.Meter;
public static readonly double RollResistanceExponent = 0.9;
public static readonly MeterPerSecond BaseWindSpeed = 3.SI().Kilo.Meter.Per.Hour.Cast<MeterPerSecond>();
}
}
\ No newline at end of file
using System;
using System.CodeDom;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
......@@ -11,6 +12,27 @@ using TUGraz.VectoCore.Exceptions;
namespace TUGraz.VectoCore.Utils
{
public class Scalar : SIBase<Scalar>
{
static Scalar()
{
Constructors.Add(typeof(Scalar), val => new Scalar(val));
}
private Scalar(double val) : base(new SI(val)) {}
public static implicit operator double(Scalar self)
{
return self.Val;
}
public static implicit operator Scalar(double val)
{
return new Scalar(val);
}
}
public class Newton : SIBase<Newton>
{
static Newton()
......@@ -553,6 +575,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>
......@@ -1023,5 +1058,14 @@ namespace TUGraz.VectoCore.Utils
}
#endregion
public Scalar Scalar()
{
var si = ToBasicUnits();
if (si.Numerator.Length == 0 && si.Denominator.Length == 0) {
return Val.SI<Scalar>();
}
throw new InvalidCastException("The SI Unit is not a scalar.");
}
}
}
\ No newline at end of file
......@@ -24,6 +24,28 @@ namespace TUGraz.VectoCore.Utils
return ((xint - x1) * (y2 - y1) / (x2 - x1) + y1).Cast<TResult>();
}
public static double Interpolate<T>(T x1, T x2, double y1, double y2, T xint)
where T : SI
{
return ((xint - x1) * (y2 - y1) / (x2 - x1) + y1).Value();
}
public static TResult Interpolate<TResult>(double x1, double x2, TResult y1, TResult y2, double xint)
where TResult : SIBase<TResult>
{
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 +77,10 @@ namespace TUGraz.VectoCore.Utils
{
return c1.CompareTo(c2) >= 0 ? c1 : c2;
}
public static T Sqrt<T>(SI si) where T : SIBase<T>
{
return si.Sqrt().Cast<T>();
}
}
}
\ No newline at end of file
......@@ -134,6 +134,7 @@
<Compile Include="Models\Connector\Ports\Impl\Response.cs" />
<Compile Include="Models\Connector\Ports\IFvPort.cs" />
<Compile Include="Models\Connector\Ports\ITnPort.cs" />
<Compile Include="Models\Declaration\AirDrag.cs" />
<Compile Include="Models\Declaration\Fan.cs" />
<Compile Include="Models\Declaration\HVAC.cs" />
<Compile Include="Models\Declaration\PneumaticSystem.cs" />
......@@ -258,9 +259,8 @@
<EmbeddedResource Include="Resources\Declaration\VAUX\SP-Table.csv" />
<EmbeddedResource Include="Resources\Declaration\VAUX\SP-Tech.csv" />
<EmbeddedResource Include="Resources\Declaration\DefaultTC.vtcc" />
<None Include="Resources\Declaration\VCDV\parameters.csv" />
<EmbeddedResource Include="Resources\Declaration\VCDV\parameters.csv" />
<EmbeddedResource Include="Resources\Declaration\WHTC-Weighting-Factors.csv" />
<EmbeddedResource Include="Resources\Declaration\WHTC.csv" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
......
......@@ -14,8 +14,8 @@ namespace TUGraz.VectoCore.Tests.Models.Declaration
[TestClass]
public class DeclarationDataTest
{
private const double Tolerance = 0.0001;
private MissionType[] missions = Enum.GetValues(typeof(MissionType)).Cast<MissionType>().ToArray();
public const double Tolerance = 0.0001;
public readonly MissionType[] Missions = Enum.GetValues(typeof(MissionType)).Cast<MissionType>().ToArray();
[TestMethod]
public void WheelDataTest()
......@@ -75,15 +75,8 @@ namespace TUGraz.VectoCore.Tests.Models.Declaration
AssertHelper.Exception<VectoException>(() => pt1.Lookup(0.RPMtoRad()));
}
[TestMethod]
public void WHTCTest()
{
Assert.Inconclusive();
}
[TestMethod]
public void WHTCWeightingTest()
{
var whtc = DeclarationData.WHTCCorrection;
......@@ -94,27 +87,94 @@ namespace TUGraz.VectoCore.Tests.Models.Declaration
};
var r = new Random();
for (var i = 0; i < missions.Length; i++) {
for (var i = 0; i < Missions.Length; i++) {
var urban = r.NextDouble() * 2;
var rural = r.NextDouble() * 2;
var motorway = r.NextDouble() * 2;
var whtcValue = whtc.Lookup(missions[i], urban, rural, motorway);
var whtcValue = whtc.Lookup(Missions[i], urban, rural, motorway);
Assert.AreEqual(urban * factors.urban[i] + rural * factors.rural[i] + motorway * factors.motorway[i], whtcValue);
}
}
[TestMethod]
public void VCDVTest()
public void AirDragTest()
{
Assert.Inconclusive();
var airDrag = DeclarationData.AirDrag;
var expected = new Dictionary<string, AirDrag.AirDragEntry> {
{ "RigidSolo", new AirDrag.AirDragEntry { A1 = 0.013526, A2 = 0.017746, A3 = -0.000666 } },
{ "RigidTrailer", new AirDrag.AirDragEntry { A1 = 0.017125, A2 = 0.072275, A3 = -0.004148 } },
{ "TractorSemitrailer", new AirDrag.AirDragEntry { A1 = 0.034767, A2 = 0.039367, A3 = -0.001897 } },
{ "CoachBus", new AirDrag.AirDragEntry { A1 = -0.000794, A2 = 0.02109, A3 = -0.00109 } }
};
foreach (var kv in expected) {
Assert.AreEqual(kv.Value, airDrag.Lookup(kv.Key));
}
var expectedCat = new Dictionary<VehicleCategory, AirDrag.AirDragEntry> {
{ VehicleCategory.RigidTruck, new AirDrag.AirDragEntry { A1 = 0.013526, A2 = 0.017746, A3 = -0.000666 } },
{ VehicleCategory.Tractor, new AirDrag.AirDragEntry { A1 = 0.034767, A2 = 0.039367, A3 = -0.001897 } },
{ VehicleCategory.CityBus, new AirDrag.AirDragEntry { A1 = -0.000794, A2 = 0.02109, A3 = -0.00109 } },
{ VehicleCategory.Coach, new AirDrag.AirDragEntry { A1 = -0.000794, A2 = 0.02109, A3 = -0.00109 } },
{ VehicleCategory.InterurbanBus, new AirDrag.AirDragEntry { A1 = -0.000794, A2 = 0.02109, A3 = -0.00109 } }
};
foreach (var kv in expectedCat) {
Assert.AreEqual(kv.Value, airDrag.Lookup(kv.Key));
}
}
[TestMethod]
public void DefaultTCTest()
{
Assert.Inconclusive();
}
var tc = DeclarationData.TorqueConverter;
var expected = new[] {
// fixed points
new { nu = 1.000, mu = 1.000, torque = 0.00 },
new { nu = 1.005, mu = 1.000, torque = 0.00 },
new { nu = 1.100, mu = 1.000, torque = -40.34 },
new { nu = 1.222, mu = 1.000, torque = -80.34 },
new { nu = 1.375, mu = 1.000, torque = -136.11 },
new { nu = 1.571, mu = 1.000, torque = -216.52 },
new { nu = 1.833, mu = 1.000, torque = -335.19 },
new { nu = 2.200, mu = 1.000, torque = -528.77 },
new { nu = 2.750, mu = 1.000, torque = -883.40 },
new { nu = 4.400, mu = 1.000, torque = -2462.17 },
new { nu = 11.000, mu = 1.000, torque = -16540.98 },
// interpolated points
new { nu = 1.0025, mu = 1.0, torque = 0.0 },
new { nu = 1.0525, mu = 1.0, torque = -20.17 },
new { nu = 1.161, mu = 1.0, torque = -60.34 },
new { nu = 1.2985, mu = 1.0, torque = -108.225 },
new { nu = 1.2985, mu = 1.0, torque = -108.225 },
new { nu = 1.473, mu = 1.0, torque = -176.315 },
new { nu = 1.702, mu = 1.0, torque = -275.855 },
new { nu = 2.0165, mu = 1.0, torque = -431.98 },
new { nu = 2.475, mu = 1.0, torque = -706.085 },
new { nu = 3.575, mu = 1.0, torque = -1672.785 },
new { nu = 7.7, mu = 1.0, torque = -9501.575 },
// extrapolated points
new { nu = 0.5, mu = 1.0, torque = 0.0 },
new { nu = 12.0, mu = 1.0, torque = -18674.133 }, // = (12-4.4)*(-16540.98- -2462.17)/(11-4.4)+ -2462.17
};
var referenceSpeed = 150.SI<PerSecond>();
var r = new Random();
foreach (var exp in expected) {
var mu = tc.LookupMu(exp.nu);
Assert.AreEqual(mu, exp.mu);
var angularSpeed = r.Next(1000).SI<PerSecond>();
var torque = tc.LookupTorque(exp.nu, angularSpeed, referenceSpeed);
AssertHelper.AreEqual(exp.torque * Math.Pow(angularSpeed.Value() / referenceSpeed.Value(), 2), torque.Value());
}
}
[TestMethod]
public void AuxElectricSystemTest()
......@@ -187,14 +247,14 @@ namespace TUGraz.VectoCore.Tests.Models.Declaration
}
};
for (var i = 0; i < missions.Length; i++) {
for (var i = 0; i < Missions.Length; i++) {
// default tech
Watt defaultValue = fan.Lookup(missions[i], "");
Watt defaultValue = fan.Lookup(Missions[i], "");
Assert.AreEqual(expected[defaultFan][i], defaultValue.Value(), Tolerance);
// all fan techs
foreach (var expect in expected) {
Watt value = fan.Lookup(missions[i], expect.Key);
Watt value = fan.Lookup(Missions[i], expect.Key);
Assert.AreEqual(expect.Value[i], value.Value(), Tolerance);
}
}
......@@ -220,9 +280,9 @@ namespace TUGraz.VectoCore.Tests.Models.Declaration
{ "12", new[] { 0, 0, 0, 0, 200, 0, 0, 0, 0, 0 } }
};
for (var i = 0; i < missions.Length; i++) {
for (var i = 0; i < Missions.Length; i++) {
foreach (var expect in expected) {
Watt value = hvac.Lookup(missions[i], expect.Key);
Watt value = hvac.Lookup(Missions[i], expect.Key);
Assert.AreEqual(expect.Value[i], value.Value(), Tolerance);
}
}
......@@ -248,9 +308,9 @@ namespace TUGraz.VectoCore.Tests.Models.Declaration
{ "12", new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
};
for (var i = 0; i < missions.Length; i++) {
for (var i = 0; i < Missions.Length; i++) {
foreach (var expect in expected) {
Watt value = ps.Lookup(missions[i], expect.Key);
Watt value = ps.Lookup(Missions[i], expect.Key);
Assert.AreEqual(expect.Value[i], value.Value(), Tolerance);
}
}
......@@ -308,8 +368,8 @@ namespace TUGraz.VectoCore.Tests.Models.Declaration
var technology = expect.Key;
foreach (var hdvClasses in expect.Value) {
var hdvClass = hdvClasses.Key;
for (var i = 0; i < missions.Length; i++) {
Watt value = sp.Lookup(missions[i], hdvClass, technology);
for (var i = 0; i < Missions.Length; i++) {
Watt value = sp.Lookup(Missions[i], hdvClass, technology);
Assert.AreEqual(hdvClasses.Value[i], value.Value(), Tolerance);
}
}
......
......@@ -151,7 +151,7 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation
while (cycleOut.Request(absTime, dt) is ResponseSuccess) {
Assert.AreEqual(absTime, outPort.AbsTime);
Assert.AreEqual(dt, outPort.Ds);
Assert.AreEqual(dt, outPort.Dt);
var time = (absTime + TimeSpan.FromTicks(dt.Ticks / 2)).TotalSeconds;
var simulationInterval = dt.TotalSeconds;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment