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 5f3029fc authored by Markus Quaritsch's avatar Markus Quaritsch
Browse files

Merge pull request #312 in VECTO/vecto-sim from ~EMKRISPMI/vecto-sim:develop to develop

* commit '3d0326fc':
  ATShiftStrategy: Disengage on angularVelocity==0
  TorqueConverter: Changed Exception-Handling. Better Performance
  ATGearbox: Moved Disengagend and TorqueConverterLocked Variables to ATGearboxState
  ATGearbox: Added Check for dryRun before engaging
  ATShiftStrategy: Removed not needed check for n_eng==0
  VectoMath Interpolate Extensions; AggressiveInlining of Methods added; DebuggerStepThrough added
  Vehicle: Corrected Check for speeds near 0. Negative Speeds are not nullified anymore.
  AuxMap: Corrections for Tests
  AuxMap: Added AuxiliaryFileHelper for Reading Auxiliary Files; Changed values in TableData from kW to W
  AuxMap: PowerDemand now in Watt in DataTable
parents 0c4b5f68 3d0326fc
No related branches found
No related tags found
No related merge requests found
Showing
with 375 additions and 305 deletions
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
*/ */
using System; using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using TUGraz.VectoCommon.Utils; using TUGraz.VectoCommon.Utils;
...@@ -66,16 +67,19 @@ namespace TUGraz.VectoCommon.Models ...@@ -66,16 +67,19 @@ namespace TUGraz.VectoCommon.Models
} }
} }
[DebuggerStepThrough]
public static string ShortName(this GearboxType type) public static string ShortName(this GearboxType type)
{ {
return type.ToString(); return type.ToString();
} }
[DebuggerStepThrough]
public static bool AutomaticTransmission(this GearboxType type) public static bool AutomaticTransmission(this GearboxType type)
{ {
return type == GearboxType.ATPowerSplit || type == GearboxType.ATSerial; return type == GearboxType.ATPowerSplit || type == GearboxType.ATSerial;
} }
[DebuggerStepThrough]
public static bool ManualTransmission(this GearboxType type) public static bool ManualTransmission(this GearboxType type)
{ {
return type == GearboxType.MT || type == GearboxType.AMT; return type == GearboxType.MT || type == GearboxType.AMT;
......
...@@ -34,6 +34,7 @@ using System.Collections.Generic; ...@@ -34,6 +34,7 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices;
namespace TUGraz.VectoCommon.Utils namespace TUGraz.VectoCommon.Utils
{ {
...@@ -59,19 +60,22 @@ namespace TUGraz.VectoCommon.Utils ...@@ -59,19 +60,22 @@ namespace TUGraz.VectoCommon.Utils
/// <param name="other">The other.</param> /// <param name="other">The other.</param>
/// <param name="tolerance">The tolerance.</param> /// <param name="tolerance">The tolerance.</param>
/// <returns></returns> /// <returns></returns>
[DebuggerHidden] [DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsEqual(this double self, double other, double tolerance = Tolerance) public static bool IsEqual(this double self, double other, double tolerance = Tolerance)
{ {
return Math.Abs(self - other) < tolerance; return Math.Abs(self - other) < tolerance;
} }
[DebuggerHidden] [DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsRelativeEqual(this SI expected, SI actual, double toleranceFactor = ToleranceFactor) public static bool IsRelativeEqual(this SI expected, SI actual, double toleranceFactor = ToleranceFactor)
{ {
return IsRelativeEqual(expected.Value(), actual.Value(), toleranceFactor: toleranceFactor); return IsRelativeEqual(expected.Value(), actual.Value(), toleranceFactor: toleranceFactor);
} }
[DebuggerHidden] [DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsRelativeEqual(this double expected, double actual, public static bool IsRelativeEqual(this double expected, double actual,
double toleranceFactor = DoubleExtensionMethods.ToleranceFactor) double toleranceFactor = DoubleExtensionMethods.ToleranceFactor)
{ {
...@@ -90,7 +94,8 @@ namespace TUGraz.VectoCommon.Utils ...@@ -90,7 +94,8 @@ namespace TUGraz.VectoCommon.Utils
/// <param name="other">The other.</param> /// <param name="other">The other.</param>
/// <param name="tolerance">The tolerance.</param> /// <param name="tolerance">The tolerance.</param>
/// <returns></returns> /// <returns></returns>
[DebuggerHidden] [DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsSmaller(this double self, double other, double tolerance = Tolerance) public static bool IsSmaller(this double self, double other, double tolerance = Tolerance)
{ {
return self < other - tolerance; return self < other - tolerance;
...@@ -103,6 +108,8 @@ namespace TUGraz.VectoCommon.Utils ...@@ -103,6 +108,8 @@ namespace TUGraz.VectoCommon.Utils
/// <param name="other">The other.</param> /// <param name="other">The other.</param>
/// <param name="tolerance">The tolerance.</param> /// <param name="tolerance">The tolerance.</param>
/// <returns></returns> /// <returns></returns>
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsSmallerOrEqual(this double self, double other, double tolerance = Tolerance) public static bool IsSmallerOrEqual(this double self, double other, double tolerance = Tolerance)
{ {
return self <= other + tolerance; return self <= other + tolerance;
...@@ -115,6 +122,8 @@ namespace TUGraz.VectoCommon.Utils ...@@ -115,6 +122,8 @@ namespace TUGraz.VectoCommon.Utils
/// <param name="other">The other.</param> /// <param name="other">The other.</param>
/// <param name="tolerance">The tolerance.</param> /// <param name="tolerance">The tolerance.</param>
/// <returns></returns> /// <returns></returns>
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsGreater(this double self, double other, double tolerance = Tolerance) public static bool IsGreater(this double self, double other, double tolerance = Tolerance)
{ {
return self > other + tolerance; return self > other + tolerance;
...@@ -127,6 +136,8 @@ namespace TUGraz.VectoCommon.Utils ...@@ -127,6 +136,8 @@ namespace TUGraz.VectoCommon.Utils
/// <param name="other">The other.</param> /// <param name="other">The other.</param>
/// <param name="tolerance">The tolerance.</param> /// <param name="tolerance">The tolerance.</param>
/// <returns></returns> /// <returns></returns>
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsGreaterOrEqual(this double self, double other, double tolerance = Tolerance) public static bool IsGreaterOrEqual(this double self, double other, double tolerance = Tolerance)
{ {
return self >= other - tolerance; return self >= other - tolerance;
...@@ -137,17 +148,39 @@ namespace TUGraz.VectoCommon.Utils ...@@ -137,17 +148,39 @@ namespace TUGraz.VectoCommon.Utils
/// </summary> /// </summary>
/// <param name="self">The self.</param> /// <param name="self">The self.</param>
/// <param name="tolerance">The tolerance.</param> /// <param name="tolerance">The tolerance.</param>
/// <returns></returns> [DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsPositive(this double self, double tolerance = Tolerance) public static bool IsPositive(this double self, double tolerance = Tolerance)
{ {
return self >= -tolerance; return self >= -tolerance;
} }
/// <summary>
/// Checks if a value is between min and max (min &lt;= value &lt;= max)
/// </summary>
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsBetween(this double self, double min, double max)
{
return min <= self && self <= max;
}
/// <summary>
/// Checks if a value is between min and max (min &lt;= value &lt;= max)
/// </summary>
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsBetween(this double self, SI min, SI max)
{
return min <= self && self <= max;
}
/// <summary> /// <summary>
/// Converts the double-value from RPM (rounds per minute) to the SI Unit PerSecond. /// Converts the double-value from RPM (rounds per minute) to the SI Unit PerSecond.
/// </summary> /// </summary>
/// <param name="self"></param> /// <param name="self"></param>
/// <returns></returns> [DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static PerSecond RPMtoRad(this double self) public static PerSecond RPMtoRad(this double self)
{ {
return SI<PerSecond>(self * 2 * Math.PI / 60.0); return SI<PerSecond>(self * 2 * Math.PI / 60.0);
...@@ -156,8 +189,8 @@ namespace TUGraz.VectoCommon.Utils ...@@ -156,8 +189,8 @@ namespace TUGraz.VectoCommon.Utils
/// <summary> /// <summary>
/// Converts the double-value from RPM (rounds per minute) to the SI Unit PerSecond. /// Converts the double-value from RPM (rounds per minute) to the SI Unit PerSecond.
/// </summary> /// </summary>
/// <param name="self"></param> [DebuggerStepThrough]
/// <returns></returns> [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static PerSecond RPMtoRad(this float self) public static PerSecond RPMtoRad(this float self)
{ {
return SI<PerSecond>(self * 2 * Math.PI / 60.0); return SI<PerSecond>(self * 2 * Math.PI / 60.0);
...@@ -166,25 +199,29 @@ namespace TUGraz.VectoCommon.Utils ...@@ -166,25 +199,29 @@ namespace TUGraz.VectoCommon.Utils
/// <summary> /// <summary>
/// Converts the value from rounds per minute to the SI Unit PerSecond /// Converts the value from rounds per minute to the SI Unit PerSecond
/// </summary> /// </summary>
/// <param name="self"></param> [DebuggerStepThrough]
/// <returns></returns> [MethodImpl(MethodImplOptions.AggressiveInlining)]
[DebuggerHidden]
public static PerSecond RPMtoRad(this int self) public static PerSecond RPMtoRad(this int self)
{ {
return SI<PerSecond>(self * 2.0 * Math.PI / 60.0); return SI<PerSecond>(self * 2.0 * Math.PI / 60.0);
} }
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static MeterPerSecond KMPHtoMeterPerSecond(this double self) public static MeterPerSecond KMPHtoMeterPerSecond(this double self)
{ {
return SI<MeterPerSecond>(self / 3.6); return SI<MeterPerSecond>(self / 3.6);
} }
[DebuggerHidden] [DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static MeterPerSecond KMPHtoMeterPerSecond(this int self) public static MeterPerSecond KMPHtoMeterPerSecond(this int self)
{ {
return SI<MeterPerSecond>(self / 3.6); return SI<MeterPerSecond>(self / 3.6);
} }
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double ToDegree(this double self) public static double ToDegree(this double self)
{ {
return self * 180.0 / Math.PI; return self * 180.0 / Math.PI;
...@@ -193,6 +230,8 @@ namespace TUGraz.VectoCommon.Utils ...@@ -193,6 +230,8 @@ namespace TUGraz.VectoCommon.Utils
/// <summary> /// <summary>
/// Creates an SI object for the number (unit-less: [-]). /// Creates an SI object for the number (unit-less: [-]).
/// </summary> /// </summary>
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static SI SI(this double value) public static SI SI(this double value)
{ {
return new SI(value); return new SI(value);
...@@ -201,17 +240,22 @@ namespace TUGraz.VectoCommon.Utils ...@@ -201,17 +240,22 @@ namespace TUGraz.VectoCommon.Utils
/// <summary> /// <summary>
/// Creates an templated SI object for the number. /// Creates an templated SI object for the number.
/// </summary> /// </summary>
[DebuggerHidden] [DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T SI<T>(this double value) where T : SIBase<T> public static T SI<T>(this double value) where T : SIBase<T>
{ {
return SIBase<T>.Create(value); return SIBase<T>.Create(value);
} }
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IEnumerable<T> SI<T>(this IEnumerable<double> self) where T : SIBase<T> public static IEnumerable<T> SI<T>(this IEnumerable<double> self) where T : SIBase<T>
{ {
return self.Select(x => x.SI<T>()); return self.Select(x => x.SI<T>());
} }
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ToGUIFormat(this double self) public static string ToGUIFormat(this double self)
{ {
return self.ToString(CultureInfo.InvariantCulture); return self.ToString(CultureInfo.InvariantCulture);
...@@ -220,7 +264,8 @@ namespace TUGraz.VectoCommon.Utils ...@@ -220,7 +264,8 @@ namespace TUGraz.VectoCommon.Utils
public static class FloatExtensionMethods public static class FloatExtensionMethods
{ {
[DebuggerHidden] [DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T SI<T>(this float value) where T : SIBase<T> public static T SI<T>(this float value) where T : SIBase<T>
{ {
return SIBase<T>.Create(value); return SIBase<T>.Create(value);
...@@ -229,6 +274,8 @@ namespace TUGraz.VectoCommon.Utils ...@@ -229,6 +274,8 @@ namespace TUGraz.VectoCommon.Utils
public static class IntegerExtensionMethods public static class IntegerExtensionMethods
{ {
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string ToGUIFormat(this int self) public static string ToGUIFormat(this int self)
{ {
return self.ToString(); return self.ToString();
......
...@@ -225,6 +225,11 @@ namespace TUGraz.VectoCommon.Utils ...@@ -225,6 +225,11 @@ namespace TUGraz.VectoCommon.Utils
} }
} }
public static IEnumerable<Tuple<TSource, TSource>> Pairwise<TSource>(this IEnumerable<TSource> source)
{
return Pairwise(source, Tuple.Create);
}
/// <summary> /// <summary>
/// Repeats the element and returns an Enumerable. /// Repeats the element and returns an Enumerable.
/// </summary> /// </summary>
......
...@@ -826,6 +826,7 @@ namespace TUGraz.VectoCommon.Utils ...@@ -826,6 +826,7 @@ namespace TUGraz.VectoCommon.Utils
/// Creates the specified special SI object. /// Creates the specified special SI object.
/// </summary> /// </summary>
/// <param name="val">The value of the SI object.</param> /// <param name="val">The value of the SI object.</param>
[DebuggerStepThrough]
public static T Create(double val) public static T Create(double val)
{ {
if (val == 0) { if (val == 0) {
...@@ -2092,6 +2093,7 @@ namespace TUGraz.VectoCommon.Utils ...@@ -2092,6 +2093,7 @@ namespace TUGraz.VectoCommon.Utils
/// <param name="si">The si.</param> /// <param name="si">The si.</param>
/// <param name="tolerance">The tolerance.</param> /// <param name="tolerance">The tolerance.</param>
/// <returns></returns> /// <returns></returns>
[DebuggerStepThrough]
public bool IsGreater(SI si, double tolerance) public bool IsGreater(SI si, double tolerance)
{ {
if (!HasEqualUnit(si)) { if (!HasEqualUnit(si)) {
...@@ -2107,6 +2109,7 @@ namespace TUGraz.VectoCommon.Utils ...@@ -2107,6 +2109,7 @@ namespace TUGraz.VectoCommon.Utils
/// <param name="si">The si.</param> /// <param name="si">The si.</param>
/// <param name="tolerance">The tolerance.</param> /// <param name="tolerance">The tolerance.</param>
/// <returns></returns> /// <returns></returns>
[DebuggerStepThrough]
public bool IsGreaterOrEqual(SI si, SI tolerance = null) public bool IsGreaterOrEqual(SI si, SI tolerance = null)
{ {
if (!HasEqualUnit(si)) { if (!HasEqualUnit(si)) {
...@@ -2125,6 +2128,7 @@ namespace TUGraz.VectoCommon.Utils ...@@ -2125,6 +2128,7 @@ namespace TUGraz.VectoCommon.Utils
/// <param name="val">The value.</param> /// <param name="val">The value.</param>
/// <param name="tolerance">The tolerance.</param> /// <param name="tolerance">The tolerance.</param>
/// <returns></returns> /// <returns></returns>
[DebuggerStepThrough]
public bool IsSmaller(double val, double tolerance = DoubleExtensionMethods.Tolerance) public bool IsSmaller(double val, double tolerance = DoubleExtensionMethods.Tolerance)
{ {
return Val.IsSmaller(val, tolerance); return Val.IsSmaller(val, tolerance);
...@@ -2136,6 +2140,7 @@ namespace TUGraz.VectoCommon.Utils ...@@ -2136,6 +2140,7 @@ namespace TUGraz.VectoCommon.Utils
/// <param name="val">The value.</param> /// <param name="val">The value.</param>
/// <param name="tolerance">The tolerance.</param> /// <param name="tolerance">The tolerance.</param>
/// <returns></returns> /// <returns></returns>
[DebuggerStepThrough]
public bool IsSmallerOrEqual(double val, double tolerance = DoubleExtensionMethods.Tolerance) public bool IsSmallerOrEqual(double val, double tolerance = DoubleExtensionMethods.Tolerance)
{ {
return Val.IsSmallerOrEqual(val, tolerance); return Val.IsSmallerOrEqual(val, tolerance);
...@@ -2147,6 +2152,7 @@ namespace TUGraz.VectoCommon.Utils ...@@ -2147,6 +2152,7 @@ namespace TUGraz.VectoCommon.Utils
/// <param name="val">The value.</param> /// <param name="val">The value.</param>
/// <param name="tolerance">The tolerance.</param> /// <param name="tolerance">The tolerance.</param>
/// <returns></returns> /// <returns></returns>
[DebuggerStepThrough]
public bool IsGreater(double val, double tolerance = DoubleExtensionMethods.Tolerance) public bool IsGreater(double val, double tolerance = DoubleExtensionMethods.Tolerance)
{ {
return Val.IsGreater(val, tolerance); return Val.IsGreater(val, tolerance);
...@@ -2158,6 +2164,7 @@ namespace TUGraz.VectoCommon.Utils ...@@ -2158,6 +2164,7 @@ namespace TUGraz.VectoCommon.Utils
/// <param name="val">The value.</param> /// <param name="val">The value.</param>
/// <param name="tolerance">The tolerance.</param> /// <param name="tolerance">The tolerance.</param>
/// <returns></returns> /// <returns></returns>
[DebuggerStepThrough]
public bool IsGreaterOrEqual(double val, double tolerance = DoubleExtensionMethods.Tolerance) public bool IsGreaterOrEqual(double val, double tolerance = DoubleExtensionMethods.Tolerance)
{ {
return Val.IsGreaterOrEqual(val, tolerance); return Val.IsGreaterOrEqual(val, tolerance);
......
...@@ -55,23 +55,68 @@ namespace TUGraz.VectoCommon.Utils ...@@ -55,23 +55,68 @@ namespace TUGraz.VectoCommon.Utils
/// <param name="y2">Second Value on the Y-Axis.</param> /// <param name="y2">Second Value on the Y-Axis.</param>
/// <param name="xint">Value on the X-Axis, for which the Y-Value should be interpolated.</param> /// <param name="xint">Value on the X-Axis, for which the Y-Value should be interpolated.</param>
/// <returns></returns> /// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TResult Interpolate<T, TResult>(T x1, T x2, TResult y1, TResult y2, T xint) where T : SI public static TResult Interpolate<T, TResult>(T x1, T x2, TResult y1, TResult y2, T xint) where T : SI
where TResult : SIBase<TResult> where TResult : SIBase<TResult>
{ {
return Interpolate(x1.Value(), x2.Value(), y1.Value(), y2.Value(), xint.Value()).SI<TResult>(); return Interpolate(x1.Value(), x2.Value(), y1.Value(), y2.Value(), xint.Value()).SI<TResult>();
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TResult Interpolate<TInput, T, TResult>(this Tuple<TInput, TInput> self, Func<TInput, T> x,
Func<TInput, TResult> y, T xInterpolate)
where T : SIBase<T>
where TResult : SIBase<TResult>
{
return Interpolate(x(self.Item1).Value(), x(self.Item2).Value(), y(self.Item1).Value(), y(self.Item2).Value(),
xInterpolate.Value()).SI<TResult>();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TResult Interpolate<TInput, TResult>(this Tuple<TInput, TInput> self, Func<TInput, double> x,
Func<TInput, TResult> y, double xInterpolate)
where TResult : SIBase<TResult>
{
return
Interpolate(x(self.Item1), x(self.Item2), y(self.Item1).Value(), y(self.Item2).Value(), xInterpolate).SI<TResult>();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TResult Interpolate<TInput, TResult>(this IEnumerable<TInput> self, Func<TInput, double> x,
Func<TInput, TResult> y, double xInterpolate)
where TResult : SIBase<TResult>
{
return self.GetSection(elem => x(elem) < xInterpolate).Interpolate(x, y, xInterpolate);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double Interpolate<TInput>(this IEnumerable<TInput> self, Func<TInput, double> x,
Func<TInput, double> y, double xInterpolate)
{
return self.GetSection(elem => x(elem) < xInterpolate).Interpolate(x, y, xInterpolate);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double Interpolate<TInput>(this Tuple<TInput, TInput> self, Func<TInput, double> x,
Func<TInput, double> y, double xInterpolate)
{
return Interpolate(x(self.Item1), x(self.Item2), y(self.Item1), y(self.Item2), xInterpolate);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double Interpolate<T>(T x1, T x2, double y1, double y2, T xint) where T : SI public static double Interpolate<T>(T x1, T x2, double y1, double y2, T xint) where T : SI
{ {
return Interpolate(x1.Value(), x2.Value(), y1, y2, xint.Value()); return Interpolate(x1.Value(), x2.Value(), y1, y2, xint.Value());
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TResult Interpolate<TResult>(double x1, double x2, TResult y1, TResult y2, double xint) public static TResult Interpolate<TResult>(double x1, double x2, TResult y1, TResult y2, double xint)
where TResult : SIBase<TResult> where TResult : SIBase<TResult>
{ {
return Interpolate(x1, x2, y1.Value(), y2.Value(), xint).SI<TResult>(); return Interpolate(x1, x2, y1.Value(), y2.Value(), xint).SI<TResult>();
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double Interpolate(Point p1, Point p2, double x) public static double Interpolate(Point p1, Point p2, double x)
{ {
return Interpolate(p1.X, p2.X, p1.Y, p2.Y, x); return Interpolate(p1.X, p2.X, p1.Y, p2.Y, x);
...@@ -80,6 +125,7 @@ namespace TUGraz.VectoCommon.Utils ...@@ -80,6 +125,7 @@ namespace TUGraz.VectoCommon.Utils
/// <summary> /// <summary>
/// Linearly interpolates a value between two points. /// Linearly interpolates a value between two points.
/// </summary> /// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double Interpolate(double x1, double x2, double y1, double y2, double xint) public static double Interpolate(double x1, double x2, double y1, double y2, double xint)
{ {
return (xint - x1) * (y2 - y1) / (x2 - x1) + y1; return (xint - x1) * (y2 - y1) / (x2 - x1) + y1;
...@@ -88,6 +134,8 @@ namespace TUGraz.VectoCommon.Utils ...@@ -88,6 +134,8 @@ namespace TUGraz.VectoCommon.Utils
/// <summary> /// <summary>
/// Returns the absolute value. /// Returns the absolute value.
/// </summary> /// </summary>
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static SI Abs(SI si) public static SI Abs(SI si)
{ {
return si.Abs(); return si.Abs();
...@@ -96,6 +144,8 @@ namespace TUGraz.VectoCommon.Utils ...@@ -96,6 +144,8 @@ namespace TUGraz.VectoCommon.Utils
/// <summary> /// <summary>
/// Returns the minimum of two values. /// Returns the minimum of two values.
/// </summary> /// </summary>
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T Min<T>(T c1, T c2) where T : IComparable public static T Min<T>(T c1, T c2) where T : IComparable
{ {
return c1.CompareTo(c2) <= 0 ? c1 : c2; return c1.CompareTo(c2) <= 0 ? c1 : c2;
...@@ -104,59 +154,67 @@ namespace TUGraz.VectoCommon.Utils ...@@ -104,59 +154,67 @@ namespace TUGraz.VectoCommon.Utils
/// <summary> /// <summary>
/// Returns the maximum of two values. /// Returns the maximum of two values.
/// </summary> /// </summary>
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T Max<T>(T c1, T c2) where T : IComparable public static T Max<T>(T c1, T c2) where T : IComparable
{ {
return c1.CompareTo(c2) >= 0 ? c1 : c2; return c1.CompareTo(c2) >= 0 ? c1 : c2;
} }
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T Max<T>(T c1, T c2, T c3) where T : IComparable public static T Max<T>(T c1, T c2, T c3) where T : IComparable
{ {
return Max(Max(c1, c2), c3); return Max(Max(c1, c2), c3);
} }
public static T Limit<T>(this T value, T lowerBound, T upperBound) where T : IComparable [DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T LimitTo<T>(this T value, T lowerBound, T upperBound) where T : IComparable
{ {
if (lowerBound.CompareTo(upperBound) > 0) { if (lowerBound.CompareTo(upperBound) > 0) {
throw new VectoException( throw new VectoException(
"VectoMath.Limit: lowerBound must not be greater than upperBound. lowerBound: {0}, upperBound: {1}", lowerBound, "VectoMath.LimitTo: lowerBound must not be greater than upperBound. lowerBound: {0}, upperBound: {1}", lowerBound,
upperBound); upperBound);
} }
if (value.CompareTo(upperBound) > 0) { if (value.CompareTo(upperBound) > 0) {
return upperBound; return upperBound;
} }
if (value.CompareTo(lowerBound) < 0) { if (value.CompareTo(lowerBound) < 0) {
return lowerBound; return lowerBound;
} }
return value; return value;
} }
/// <summary> /// <summary>
/// converts the given inclination in percent (0-1+) into Radians /// converts the given inclination in percent (0-1+) into Radians
/// </summary> /// </summary>
/// <param name="inclinationPercent"></param> [DebuggerStepThrough]
/// <returns></returns> [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Radian InclinationToAngle(double inclinationPercent) public static Radian InclinationToAngle(double inclinationPercent)
{ {
return Math.Atan(inclinationPercent).SI<Radian>(); return Math.Atan(inclinationPercent).SI<Radian>();
} }
public static List<double> QuadraticEquationSolver(double a, double b, double c) public static double[] QuadraticEquationSolver(double a, double b, double c)
{ {
var retVal = new List<double>();
var d = b * b - 4 * a * c; var d = b * b - 4 * a * c;
// no real solution
if (d < 0) { if (d < 0) {
return retVal; return new double[0];
} else if (d > 0) {
// two solutions possible
retVal.Add((-b + Math.Sqrt(d)) / (2 * a));
retVal.Add((-b - Math.Sqrt(d)) / (2 * a));
} else {
// only one solution possible
retVal.Add(-b / (2 * a));
} }
return retVal;
if (d > 0) {
// two solutions
return new[] { (-b + Math.Sqrt(d)) / (2 * a), (-b - Math.Sqrt(d)) / (2 * a) };
}
// one real solution
return new[] { -b / (2 * a) };
} }
public static Point Intersect(Edge line1, Edge line2) public static Point Intersect(Edge line1, Edge line2)
...@@ -221,10 +279,10 @@ namespace TUGraz.VectoCommon.Utils ...@@ -221,10 +279,10 @@ namespace TUGraz.VectoCommon.Utils
// we need to accelerate / decelerate. solve quadratic equation... // we need to accelerate / decelerate. solve quadratic equation...
// ds = acceleration / 2 * dt^2 + currentSpeed * dt => solve for dt // ds = acceleration / 2 * dt^2 + currentSpeed * dt => solve for dt
var solutions = VectoMath.QuadraticEquationSolver(acceleration.Value() / 2.0, currentSpeed.Value(), var solutions = QuadraticEquationSolver(acceleration.Value() / 2.0, currentSpeed.Value(),
-ds.Value()); -ds.Value());
if (solutions.Count == 0) { if (solutions.Length == 0) {
// no real-valued solutions: acceleration is so negative that vehicle stops already before the required distance can be reached. // no real-valued solutions: acceleration is so negative that vehicle stops already before the required distance can be reached.
// adapt ds to the halting-point. // adapt ds to the halting-point.
// t = v / a // t = v / a
...@@ -256,12 +314,14 @@ namespace TUGraz.VectoCommon.Utils ...@@ -256,12 +314,14 @@ namespace TUGraz.VectoCommon.Utils
return retVal; return retVal;
} }
[DebuggerStepThrough]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T Ceiling<T>(T si) where T : SIBase<T> public static T Ceiling<T>(T si) where T : SIBase<T>
{ {
return Math.Ceiling(si.Value()).SI<T>(); return Math.Ceiling(si.Value()).SI<T>();
} }
public static List<double> CubicEquationSolver(double a, double b, double c, double d) public static double[] CubicEquationSolver(double a, double b, double c, double d)
{ {
var solutions = new List<double>(); var solutions = new List<double>();
if (a.IsEqual(0, 1e-12)) { if (a.IsEqual(0, 1e-12)) {
...@@ -280,7 +340,7 @@ namespace TUGraz.VectoCommon.Utils ...@@ -280,7 +340,7 @@ namespace TUGraz.VectoCommon.Utils
solutions.Add(p * Math.Cos((phi + 2 * i * Math.PI) / 3.0) - w); solutions.Add(p * Math.Cos((phi + 2 * i * Math.PI) / 3.0) - w);
} }
} else { } else {
// only one real solution // one real solution
discriminant = Math.Sqrt(discriminant); discriminant = Math.Sqrt(discriminant);
solutions.Add(Cbrt(q + discriminant) + Cbrt(q - discriminant) - w); solutions.Add(Cbrt(q + discriminant) + Cbrt(q - discriminant) - w);
} }
...@@ -293,7 +353,7 @@ namespace TUGraz.VectoCommon.Utils ...@@ -293,7 +353,7 @@ namespace TUGraz.VectoCommon.Utils
} }
} }
solutions.Sort(); solutions.Sort();
return solutions; return solutions.ToArray();
} }
private static double Cbrt(double x) private static double Cbrt(double x)
...@@ -336,27 +396,11 @@ namespace TUGraz.VectoCommon.Utils ...@@ -336,27 +396,11 @@ namespace TUGraz.VectoCommon.Utils
return new Point(p1.X * scalar, p1.Y * scalar, p1.Z * scalar); return new Point(p1.X * scalar, p1.Y * scalar, p1.Z * scalar);
} }
/// <summary>
///
/// </summary>
/// <param name="scalar"></param>
/// <param name="p1"></param>
/// <returns></returns>
public static Point operator *(double scalar, Point p1) public static Point operator *(double scalar, Point p1)
{ {
return p1 * scalar; return p1 * scalar;
} }
/// <summary>
/// Calculates cross product between two 3d-vectors.
/// </summary>
/// <param name="other"></param>
/// <returns></returns>
public Point Cross(Point other)
{
return new Point(Y * other.Z - Z * other.Y, Z * other.X - X * other.Z, X * other.Y - Y * other.X);
}
/// <summary> /// <summary>
/// Returns perpendicular vector for xy-components of this point. P = (-Y, X) /// Returns perpendicular vector for xy-components of this point. P = (-Y, X)
/// </summary> /// </summary>
...@@ -422,14 +466,6 @@ namespace TUGraz.VectoCommon.Utils ...@@ -422,14 +466,6 @@ namespace TUGraz.VectoCommon.Utils
public readonly double Z; public readonly double Z;
public readonly double W; public readonly double W;
public Plane(double x, double y, double z, double w)
{
X = x;
Y = y;
Z = z;
W = w;
}
public Plane(Triangle tr) public Plane(Triangle tr)
{ {
var abX = tr.P2.X - tr.P1.X; var abX = tr.P2.X - tr.P1.X;
...@@ -466,13 +502,8 @@ namespace TUGraz.VectoCommon.Utils ...@@ -466,13 +502,8 @@ namespace TUGraz.VectoCommon.Utils
} }
/// <summary> /// <summary>
/// Barycentric Technique: http://www.blackpawn.com/texts/pointinpoly/default.html /// Check if Point is inside of Triangle. Barycentric Technique: http://www.blackpawn.com/texts/pointinpoly/default.html
/// </summary> /// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="exact"></param>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsInside(double x, double y, bool exact) public bool IsInside(double x, double y, bool exact)
{ {
var smallerY = y - DoubleExtensionMethods.Tolerance; var smallerY = y - DoubleExtensionMethods.Tolerance;
...@@ -530,17 +561,6 @@ namespace TUGraz.VectoCommon.Utils ...@@ -530,17 +561,6 @@ namespace TUGraz.VectoCommon.Utils
var result = p0Square * det12 + p1Square * det20 + p2Square * det01; var result = p0Square * det12 + p1Square * det20 + p2Square * det01;
return result > 0; return result > 0;
//double[,] m = { { P1.X - p.X, P1.Y - p.Y, (P1.X * P1.X - p.X*p.X) + (P1.Y * P1.Y - p.Y*p.Y) },
// { P2.X - p.X, P2.Y - p.Y, (P2.X * P2.X - p.X*p.X) + (P2.Y * P2.Y - p.Y*p.Y) },
// { P3.X - p.X, P3.Y - p.Y, (P3.X * P3.X - p.X*p.X) + (P3.Y * P3.Y - p.Y*p.Y) } };
//var det = m[0, 0] * m[1, 1] * m[2, 2]
// + m[0, 1] * m[1, 2] * m[2, 0]
// + m[0, 2] * m[1, 0] * m[2, 1]
// - m[0, 0] * m[1, 2] * m[2, 1]
// - m[0, 1] * m[1, 0] * m[2, 2]
// - m[0, 2] * m[1, 1] * m[2, 0];
//return det > 0;
} }
public bool Contains(Point p) public bool Contains(Point p)
...@@ -553,7 +573,7 @@ namespace TUGraz.VectoCommon.Utils ...@@ -553,7 +573,7 @@ namespace TUGraz.VectoCommon.Utils
return Contains(t.P1) || Contains(t.P2) || Contains(t.P3); return Contains(t.P1) || Contains(t.P2) || Contains(t.P3);
} }
public Edge[] GetEdges() public IEnumerable<Edge> GetEdges()
{ {
return new[] { new Edge(P1, P2), new Edge(P2, P3), new Edge(P3, P1) }; return new[] { new Edge(P1, P2), new Edge(P2, P3), new Edge(P3, P1) };
} }
......
using System.Data;
using System.IO;
using System.Text;
using TUGraz.VectoCommon.Exceptions;
using TUGraz.VectoCommon.Utils;
using TUGraz.VectoCore.InputData.Impl;
using TUGraz.VectoCore.InputData.Reader.ComponentData;
using TUGraz.VectoCore.Utils;
namespace TUGraz.VectoCore.InputData
{
public static class AuxiliaryFileHelper
{
public static void FillAuxiliaryDataInputData(AuxiliaryDataInputData auxData, string auxFile)
{
try {
var stream = new StreamReader(auxFile);
stream.ReadLine(); // skip header "Transmission ration to engine rpm [-]"
auxData.TransmissionRatio = stream.ReadLine().IndulgentParse();
stream.ReadLine(); // skip header "Efficiency to engine [-]"
auxData.EfficiencyToEngine = stream.ReadLine().IndulgentParse();
stream.ReadLine(); // skip header "Efficiency auxiliary to supply [-]"
auxData.EfficiencyToSupply = stream.ReadLine().IndulgentParse();
var table = VectoCSVFile.ReadStream(new MemoryStream(Encoding.UTF8.GetBytes(stream.ReadToEnd())), source: auxFile);
foreach (DataRow row in table.Rows) {
if (AuxiliaryDataReader.HeaderIsValid(table.Columns)) {
row[AuxiliaryDataReader.Fields.MechPower] =
row.ParseDouble(AuxiliaryDataReader.Fields.MechPower).SI().Kilo.Watt.Value();
row[AuxiliaryDataReader.Fields.SupplyPower] =
row.ParseDouble(AuxiliaryDataReader.Fields.SupplyPower).SI().Kilo.Watt.Value();
} else {
row[1] = row.ParseDouble(1).SI().Kilo.Watt.Value();
row[2] = row.ParseDouble(2).SI().Kilo.Watt.Value();
}
}
auxData.DemandMap = table;
} catch (FileNotFoundException e) {
throw new VectoException("Auxiliary file not found: " + auxFile, e);
}
}
}
}
\ No newline at end of file
...@@ -32,10 +32,8 @@ ...@@ -32,10 +32,8 @@
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using TUGraz.VectoCommon.Exceptions; using TUGraz.VectoCommon.Exceptions;
using TUGraz.VectoCommon.InputData; using TUGraz.VectoCommon.InputData;
using TUGraz.VectoCommon.Models; using TUGraz.VectoCommon.Models;
...@@ -556,14 +554,8 @@ namespace TUGraz.VectoCore.InputData.FileIO.JSON ...@@ -556,14 +554,8 @@ namespace TUGraz.VectoCore.InputData.FileIO.JSON
if (auxFile == null || EmptyOrInvalidFileName(auxFile.Value<string>())) { if (auxFile == null || EmptyOrInvalidFileName(auxFile.Value<string>())) {
continue; continue;
} }
var stream = new StreamReader(Path.Combine(BasePath, auxFile.Value<string>()));
stream.ReadLine(); // skip header "Transmission ration to engine rpm [-]" AuxiliaryFileHelper.FillAuxiliaryDataInputData(auxData, Path.Combine(BasePath, auxFile.Value<string>()));
auxData.TransmissionRatio = stream.ReadLine().IndulgentParse();
stream.ReadLine(); // skip header "Efficiency to engine [-]"
auxData.EfficiencyToEngine = stream.ReadLine().IndulgentParse();
stream.ReadLine(); // skip header "Efficiency auxiliary to supply [-]"
auxData.EfficiencyToSupply = stream.ReadLine().IndulgentParse();
auxData.DemandMap = VectoCSVFile.ReadStream(new MemoryStream(Encoding.UTF8.GetBytes(stream.ReadToEnd())), source: Path.Combine(BasePath, auxFile.Value<string>()));
} }
return retVal; return retVal;
} }
...@@ -635,14 +627,7 @@ namespace TUGraz.VectoCore.InputData.FileIO.JSON ...@@ -635,14 +627,7 @@ namespace TUGraz.VectoCore.InputData.FileIO.JSON
if (auxFile == null || EmptyOrInvalidFileName(auxFile.Value<string>())) { if (auxFile == null || EmptyOrInvalidFileName(auxFile.Value<string>())) {
continue; continue;
} }
var stream = new StreamReader(Path.Combine(BasePath, auxFile.Value<string>())); AuxiliaryFileHelper.FillAuxiliaryDataInputData(auxData, Path.Combine(BasePath, auxFile.Value<string>()));
stream.ReadLine(); // skip header "Transmission ration to engine rpm [-]"
auxData.TransmissionRatio = stream.ReadLine().IndulgentParse();
stream.ReadLine(); // skip header "Efficiency to engine [-]"
auxData.EfficiencyToEngine = stream.ReadLine().IndulgentParse();
stream.ReadLine(); // skip header "Efficiency auxiliary to supply [-]"
auxData.EfficiencyToSupply = stream.ReadLine().IndulgentParse();
auxData.DemandMap = VectoCSVFile.ReadStream(new MemoryStream(Encoding.UTF8.GetBytes(stream.ReadToEnd())), source: Path.Combine(BasePath, auxFile.Value<string>()));
} }
return retVal; return retVal;
} }
......
...@@ -56,36 +56,6 @@ namespace TUGraz.VectoCore.InputData.Reader.ComponentData ...@@ -56,36 +56,6 @@ namespace TUGraz.VectoCore.InputData.Reader.ComponentData
return new AuxiliaryData(data.TransmissionRatio, data.EfficiencyToEngine, data.EfficiencyToSupply, map); return new AuxiliaryData(data.TransmissionRatio, data.EfficiencyToEngine, data.EfficiencyToSupply, map);
} }
/// <summary>
/// Reads the demand map from a file.
/// </summary>
/// <param name="fileName"></param>
/// <param name="id"></param>
/// <returns></returns>
public static AuxiliaryData ReadFromFile(string fileName, string id)
{
try {
using (var reader = new StreamReader(fileName)) {
reader.ReadLine(); // skip header "Transmission ration to engine rpm [-]"
var transmissionRatio = reader.ReadLine().IndulgentParse();
reader.ReadLine(); // skip header "Efficiency to engine [-]"
var efficiencyToEngine = reader.ReadLine().IndulgentParse();
reader.ReadLine(); // skip header "Efficiency auxiliary to supply [-]"
var efficiencyToSupply = reader.ReadLine().IndulgentParse();
var m = new MemoryStream(Encoding.UTF8.GetBytes(reader.ReadToEnd()));
reader.Close();
var table = VectoCSVFile.ReadStream(m);
var map = ReadAuxMap(id, table);
return new AuxiliaryData(transmissionRatio, efficiencyToEngine, efficiencyToSupply, map);
}
} catch (FileNotFoundException e) {
throw new VectoException("Auxiliary file not found: " + fileName, e);
}
}
private static DelaunayMap ReadAuxMap(string id, DataTable table) private static DelaunayMap ReadAuxMap(string id, DataTable table)
{ {
var map = new DelaunayMap(id); var map = new DelaunayMap(id);
...@@ -103,9 +73,7 @@ namespace TUGraz.VectoCore.InputData.Reader.ComponentData ...@@ -103,9 +73,7 @@ namespace TUGraz.VectoCore.InputData.Reader.ComponentData
{ {
for (var i = 0; i < table.Rows.Count; i++) { for (var i = 0; i < table.Rows.Count; i++) {
var row = table.Rows[i]; var row = table.Rows[i];
map.AddPoint(row.ParseDouble(0).RPMtoRad().Value(), map.AddPoint(row.ParseDouble(0).RPMtoRad().Value(),row.ParseDouble(2),row.ParseDouble(1));
row.ParseDouble(1).SI().Kilo.Watt.Cast<Watt>().Value(),
row.ParseDouble(2).SI().Kilo.Watt.Cast<Watt>().Value());
} }
} }
...@@ -113,13 +81,11 @@ namespace TUGraz.VectoCore.InputData.Reader.ComponentData ...@@ -113,13 +81,11 @@ namespace TUGraz.VectoCore.InputData.Reader.ComponentData
{ {
for (var i = 0; i < table.Rows.Count; i++) { for (var i = 0; i < table.Rows.Count; i++) {
var row = table.Rows[i]; var row = table.Rows[i];
map.AddPoint(row.ParseDouble(Fields.AuxSpeed).RPMtoRad().Value(), map.AddPoint(row.ParseDouble(Fields.AuxSpeed).RPMtoRad().Value(),row.ParseDouble(Fields.SupplyPower),row.ParseDouble(Fields.MechPower));
row.ParseDouble(Fields.MechPower).SI().Kilo.Watt.Cast<Watt>().Value(),
row.ParseDouble(Fields.SupplyPower).SI().Kilo.Watt.Cast<Watt>().Value());
} }
} }
private static bool HeaderIsValid(DataColumnCollection columns) public static bool HeaderIsValid(DataColumnCollection columns)
{ {
return columns.Contains(Fields.AuxSpeed) && columns.Contains(Fields.MechPower) && return columns.Contains(Fields.AuxSpeed) && columns.Contains(Fields.MechPower) &&
columns.Contains(Fields.SupplyPower); columns.Contains(Fields.SupplyPower);
......
...@@ -71,16 +71,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine ...@@ -71,16 +71,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine
return Formulas.TorqueToPower(DragLoadStationaryTorque(angularVelocity), angularVelocity); return Formulas.TorqueToPower(DragLoadStationaryTorque(angularVelocity), angularVelocity);
} }
public CombustionEngineData EngineData { get; internal set; } public CombustionEngineData EngineData { get; internal set; }
public Second PT1(PerSecond angularVelocity) public Second PT1(PerSecond angularVelocity)
{ {
return PT1Data.Lookup(angularVelocity); return PT1Data.Lookup(angularVelocity);
} }
/// <summary> /// <summary>
/// Get the engine's preferred speed from the given full-load curve (i.e. Speed at 51% torque/speed-integral between idling and N95h.) /// Get the engine's preferred speed from the given full-load curve (i.e. Speed at 51% torque/speed-integral between idling and N95h.)
/// </summary> /// </summary>
...@@ -105,7 +102,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine ...@@ -105,7 +102,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine
get { return _n95hSpeed ?? (_n95hSpeed = FindEngineSpeedForPower(0.95 * MaxPower).Last()); } get { return _n95hSpeed ?? (_n95hSpeed = FindEngineSpeedForPower(0.95 * MaxPower).Last()); }
} }
public PerSecond LoSpeed public PerSecond LoSpeed
{ {
get { return _engineSpeedLo ?? (_engineSpeedLo = FindEngineSpeedForPower(0.55 * MaxPower).First()); } get { return _engineSpeedLo ?? (_engineSpeedLo = FindEngineSpeedForPower(0.55 * MaxPower).First()); }
...@@ -116,7 +112,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine ...@@ -116,7 +112,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine
get { return _engineSpeedHi ?? (_engineSpeedHi = FindEngineSpeedForPower(0.7 * MaxPower).Last()); } get { return _engineSpeedHi ?? (_engineSpeedHi = FindEngineSpeedForPower(0.7 * MaxPower).Last()); }
} }
public NewtonMeter MaxLoadTorque public NewtonMeter MaxLoadTorque
{ {
get { return FullLoadEntries.Max(x => x.TorqueFullLoad); } get { return FullLoadEntries.Max(x => x.TorqueFullLoad); }
...@@ -127,7 +122,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine ...@@ -127,7 +122,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine
get { return FullLoadEntries.Min(x => x.TorqueDrag); } get { return FullLoadEntries.Min(x => x.TorqueDrag); }
} }
private void ComputePreferredSpeed() private void ComputePreferredSpeed()
{ {
var maxArea = ComputeArea(EngineData.IdleSpeed, N95hSpeed); var maxArea = ComputeArea(EngineData.IdleSpeed, N95hSpeed);
...@@ -161,10 +155,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine ...@@ -161,10 +155,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Engine
// area = (M(n1) + M(n2))/2 * (n2 - n1) => solve for n2 // area = (M(n1) + M(n2))/2 * (n2 - n1) => solve for n2
var retVal = VectoMath.QuadraticEquationSolver(k.Value() / 2.0, d.Value(), var retVal = VectoMath.QuadraticEquationSolver(k.Value() / 2.0, d.Value(),
(-k * p1.EngineSpeed * p1.EngineSpeed / 2 - p1.EngineSpeed * d - area).Value()); (-k * p1.EngineSpeed * p1.EngineSpeed / 2 - p1.EngineSpeed * d - area).Value());
if (retVal.Count == 0) { if (retVal.Length == 0) {
Log.Info("No real solution found for requested area: P: {0}, p1: {1}, p2: {2}", area, p1, p2); Log.Info("No real solution found for requested area: P: {0}, p1: {1}, p2: {2}", area, p1, p2);
} }
return retVal.First(x => x >= p1.EngineSpeed && x <= p2.EngineSpeed).SI<PerSecond>(); return retVal.First(x => x.IsBetween(p1.EngineSpeed, p2.EngineSpeed)).SI<PerSecond>();
} }
private List<PerSecond> FindEngineSpeedForPower(Watt power) private List<PerSecond> FindEngineSpeedForPower(Watt power)
......
...@@ -34,12 +34,13 @@ using System.Collections.Generic; ...@@ -34,12 +34,13 @@ using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Linq; using System.Linq;
using TUGraz.VectoCommon.Exceptions; using TUGraz.VectoCommon.Exceptions;
using TUGraz.VectoCommon.Models;
using TUGraz.VectoCommon.Utils; using TUGraz.VectoCommon.Utils;
namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
{ {
[CustomValidation(typeof(TorqueConverterData), "ValidateData")] [CustomValidation(typeof(TorqueConverterData), "ValidateData")]
public class TorqueConverterData public class TorqueConverterData : LoggingObject
{ {
protected List<TorqueConverterEntry> TorqueConverterEntries; protected List<TorqueConverterEntry> TorqueConverterEntries;
...@@ -95,34 +96,33 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox ...@@ -95,34 +96,33 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
(mpNorm * mpNorm); (mpNorm * mpNorm);
var c = angularSpeedOut.Value() * angularSpeedOut.Value() * mpEdge.SlopeXY * muEdge.SlopeXY / (mpNorm * mpNorm) - var c = angularSpeedOut.Value() * angularSpeedOut.Value() * mpEdge.SlopeXY * muEdge.SlopeXY / (mpNorm * mpNorm) -
torqueOut.Value(); torqueOut.Value();
var sol = VectoMath.QuadraticEquationSolver(a, b, c);
var selected = sol.Where(x => x > min solutions.AddRange(VectoMath.QuadraticEquationSolver(a, b, c).Where(x => {
&& angularSpeedOut.Value() / x >= muEdge.P1.X && angularSpeedOut.Value() / x < muEdge.P2.X var ratio = angularSpeedOut.Value() / x;
&& angularSpeedOut.Value() / x >= mpEdge.P1.X && angularSpeedOut.Value() / x < mpEdge.P2.X); return x > min && muEdge.P1.X <= ratio && ratio < muEdge.P2.X;
solutions.AddRange(selected); }));
} }
if (solutions.Count == 0) { if (solutions.Count == 0) {
throw new VectoException("No solution for input torque/input speed found! n_out: {0}, tq_out: {1}", angularSpeedOut, Log.Debug(
torqueOut); "TorqueConverterData::FindOperatingPoint No solution for input torque/input speed found! n_out: {0}, tq_out: {1}",
angularSpeedOut, torqueOut);
} }
var retVal = new List<TorqueConverterOperatingPoint>(); return solutions.Select(sol => {
foreach (var sol in solutions) { var s = sol.SI<PerSecond>();
var tmp = new TorqueConverterOperatingPoint { var mu = MuLookup(angularSpeedOut / s);
return new TorqueConverterOperatingPoint {
OutTorque = torqueOut, OutTorque = torqueOut,
OutAngularVelocity = angularSpeedOut, OutAngularVelocity = angularSpeedOut,
InAngularVelocity = sol.SI<PerSecond>() InAngularVelocity = s,
SpeedRatio = angularSpeedOut / s,
TorqueRatio = mu,
InTorque = torqueOut / mu,
}; };
tmp.SpeedRatio = angularSpeedOut / tmp.InAngularVelocity; }).ToList();
tmp.TorqueRatio = MuLookup(angularSpeedOut / tmp.InAngularVelocity);
tmp.InTorque = torqueOut / tmp.TorqueRatio;
retVal.Add(tmp);
}
return retVal;
} }
/// <summary> /// <summary>
/// find an operating point for the torque converter /// find an operating point for the torque converter
/// ///
...@@ -139,31 +139,30 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox ...@@ -139,31 +139,30 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
OutAngularVelocity = outAngularVelocity, OutAngularVelocity = outAngularVelocity,
SpeedRatio = outAngularVelocity.Value() / inAngularVelocity.Value(), SpeedRatio = outAngularVelocity.Value() / inAngularVelocity.Value(),
}; };
foreach (var segment in TorqueConverterEntries.Pairwise(Tuple.Create)) {
if (!(retVal.SpeedRatio >= segment.Item1.SpeedRatio) || !(retVal.SpeedRatio < segment.Item2.SpeedRatio)) { foreach (var segment in TorqueConverterEntries.Pairwise()) {
continue; if (retVal.SpeedRatio.IsBetween(segment.Item1.SpeedRatio, segment.Item2.SpeedRatio)) {
} var mpTorque = segment.Interpolate(x => x.SpeedRatio, y => y.Torque, retVal.SpeedRatio);
var mpTorque = VectoMath.Interpolate(segment.Item1.SpeedRatio, segment.Item2.SpeedRatio, segment.Item1.Torque, retVal.TorqueRatio = segment.Interpolate(x => x.SpeedRatio, y => y.TorqueRatio, retVal.SpeedRatio);
segment.Item2.Torque, retVal.SpeedRatio);
retVal.TorqueRatio = VectoMath.Interpolate(segment.Item1.SpeedRatio, segment.Item2.SpeedRatio,
segment.Item1.TorqueRatio, segment.Item2.TorqueRatio, retVal.SpeedRatio);
retVal.InTorque = mpTorque * (inAngularVelocity * inAngularVelocity / ReferenceSpeed / ReferenceSpeed).Value(); retVal.InTorque = mpTorque * (inAngularVelocity * inAngularVelocity / ReferenceSpeed / ReferenceSpeed).Value();
retVal.OutTorque = retVal.InTorque * retVal.TorqueRatio; retVal.OutTorque = retVal.InTorque * retVal.TorqueRatio;
return retVal; return retVal;
} }
}
// No solution found. Throw Errror
var nu = outAngularVelocity / inAngularVelocity; var nu = outAngularVelocity / inAngularVelocity;
var nuMax = TorqueConverterEntries.Last().SpeedRatio; var nuMax = TorqueConverterEntries.Last().SpeedRatio;
if (nu.IsGreater(nuMax)) { if (nu.IsGreater(nuMax)) {
throw new VectoException( throw new VectoException(
"Torque Converter: Range of torque converter data is not sufficient. Needed nu: {0}, Got nu_max: {1}", nu, "Torque Converter: Range of torque converter data is not sufficient. Needed nu: {0}, Got nu_max: {1}", nu, nuMax);
nuMax); }
} else {
throw new VectoException( throw new VectoException(
"Torque Converter: No solution for output speed/input speed found! n_out: {0}, n_in: {1}, nu: {2}, nu_max: {3}", "Torque Converter: No solution for output speed/input speed found! n_out: {0}, n_in: {1}, nu: {2}, nu_max: {3}",
outAngularVelocity, inAngularVelocity, nu, nuMax); outAngularVelocity, inAngularVelocity, nu, nuMax);
} }
}
/// <summary> /// <summary>
/// find an operating point for the torque converter /// find an operating point for the torque converter
...@@ -187,7 +186,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox ...@@ -187,7 +186,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
} }
var solutions = new List<double>(); var solutions = new List<double>();
// ReSharper disable once LoopCanBeConvertedToQuery
foreach (var edge in TorqueConverterEntries.Pairwise( foreach (var edge in TorqueConverterEntries.Pairwise(
(p1, p2) => Edge.Create(new Point(p1.SpeedRatio, p1.Torque.Value()), new Point(p2.SpeedRatio, p2.Torque.Value())))) { (p1, p2) => Edge.Create(new Point(p1.SpeedRatio, p1.Torque.Value()), new Point(p2.SpeedRatio, p2.Torque.Value())))) {
var x = (referenceTorque - edge.OffsetXY) / edge.SlopeXY; var x = (referenceTorque - edge.OffsetXY) / edge.SlopeXY;
...@@ -206,9 +204,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox ...@@ -206,9 +204,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
public TorqueConverterOperatingPoint FindOperatingPointForPowerDemand(Watt power, PerSecond prevInputSpeed, public TorqueConverterOperatingPoint FindOperatingPointForPowerDemand(Watt power, PerSecond prevInputSpeed,
PerSecond nextOutputSpeed, KilogramSquareMeter inertia, Second dt) PerSecond nextOutputSpeed, KilogramSquareMeter inertia, Second dt)
{ {
//var retVal = new TorqueConverterOperatingPoint {
// OutAngularVelocity = nextOutputSpeed
//};
var solutions = new List<double>(); var solutions = new List<double>();
var mpNorm = ReferenceSpeed.Value(); var mpNorm = ReferenceSpeed.Value();
...@@ -238,22 +233,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox ...@@ -238,22 +233,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox
private double MuLookup(double speedRatio) private double MuLookup(double speedRatio)
{ {
int index; return TorqueConverterEntries.Interpolate(x => x.SpeedRatio, y => y.TorqueRatio, speedRatio);
TorqueConverterEntries.GetSection(x => x.SpeedRatio < speedRatio, out index);
var retVal = VectoMath.Interpolate(TorqueConverterEntries[index].SpeedRatio,
TorqueConverterEntries[index + 1].SpeedRatio, TorqueConverterEntries[index].TorqueRatio,
TorqueConverterEntries[index + 1].TorqueRatio, speedRatio);
return retVal;
} }
private NewtonMeter ReferenceTorqueLookup(double speedRatio) private NewtonMeter ReferenceTorqueLookup(double speedRatio)
{ {
int index; return TorqueConverterEntries.Interpolate(x => x.SpeedRatio, y => y.Torque, speedRatio);
TorqueConverterEntries.GetSection(x => x.SpeedRatio < speedRatio, out index);
var retVal = VectoMath.Interpolate(TorqueConverterEntries[index].SpeedRatio,
TorqueConverterEntries[index + 1].SpeedRatio, TorqueConverterEntries[index].Torque,
TorqueConverterEntries[index + 1].Torque, speedRatio);
return retVal;
} }
// ReSharper disable once UnusedMember.Global -- used by validation // ReSharper disable once UnusedMember.Global -- used by validation
......
...@@ -46,28 +46,29 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl ...@@ -46,28 +46,29 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
{ {
public class ATGearbox : AbstractGearbox<ATGearbox.ATGearboxState> public class ATGearbox : AbstractGearbox<ATGearbox.ATGearboxState>
{ {
protected internal bool Disengaged = true; private readonly IShiftStrategy _strategy;
private readonly IShiftStrategy Strategy;
protected internal readonly TorqueConverter TorqueConverter; protected internal readonly TorqueConverter TorqueConverter;
private IIdleController _idleController;
// state overlapping property
public Second LastShift { get; private set; } public Second LastShift { get; private set; }
public bool TorqueConverterLocked
{
get { return CurrentState.TorqueConverterLocked; }
set { CurrentState.TorqueConverterLocked = value; }
}
public ATGearbox(IVehicleContainer container, GearboxData gearboxModelData, IShiftStrategy strategy, public ATGearbox(IVehicleContainer container, GearboxData gearboxModelData, IShiftStrategy strategy,
KilogramSquareMeter engineInertia) KilogramSquareMeter engineInertia)
: base(container, gearboxModelData) : base(container, gearboxModelData)
{ {
Strategy = strategy; _strategy = strategy;
Strategy.Gearbox = this; _strategy.Gearbox = this;
LastShift = -double.MaxValue.SI<Second>(); LastShift = -double.MaxValue.SI<Second>();
TorqueConverter = new TorqueConverter(this, Strategy, container, gearboxModelData.TorqueConverterData, engineInertia); TorqueConverter = new TorqueConverter(this, _strategy, container, gearboxModelData.TorqueConverterData, engineInertia);
} }
private IIdleController _idleController;
public bool TorqueConverterLocked { get; protected internal set; }
public IIdleController IdleController public IIdleController IdleController
{ {
get { return _idleController; } get { return _idleController; }
...@@ -78,23 +79,34 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl ...@@ -78,23 +79,34 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
} }
} }
public bool Disengaged
{
get { return CurrentState.Disengaged; }
set { CurrentState.Disengaged = value; }
}
public override void Connect(ITnOutPort other) public override void Connect(ITnOutPort other)
{ {
base.Connect(other); base.Connect(other);
TorqueConverter.NextComponent = other; TorqueConverter.NextComponent = other;
} }
public override bool ClutchClosed(Second absTime)
{
return true;
}
public override IResponse Initialize(NewtonMeter outTorque, PerSecond outAngularVelocity) public override IResponse Initialize(NewtonMeter outTorque, PerSecond outAngularVelocity)
{ {
if (Disengaged) { if (CurrentState.Disengaged) {
Gear = Strategy.InitGear(0.SI<Second>(), Constants.SimulationSettings.TargetTimeInterval, outTorque, Gear = _strategy.InitGear(0.SI<Second>(), Constants.SimulationSettings.TargetTimeInterval, outTorque,
outAngularVelocity); outAngularVelocity);
} }
var inAngularVelocity = 0.SI<PerSecond>(); var inAngularVelocity = 0.SI<PerSecond>();
var inTorque = 0.SI<NewtonMeter>(); var inTorque = 0.SI<NewtonMeter>();
var effectiveRatio = ModelData.Gears[Gear].Ratio; var effectiveRatio = ModelData.Gears[Gear].Ratio;
var effectiveLossMap = ModelData.Gears[Gear].LossMap; var effectiveLossMap = ModelData.Gears[Gear].LossMap;
if (!TorqueConverterLocked) { if (!CurrentState.TorqueConverterLocked) {
effectiveRatio = ModelData.Gears[Gear].TorqueConverterRatio; effectiveRatio = ModelData.Gears[Gear].TorqueConverterRatio;
effectiveLossMap = ModelData.Gears[Gear].TorqueConverterGearLossMap; effectiveLossMap = ModelData.Gears[Gear].TorqueConverterGearLossMap;
} }
...@@ -105,20 +117,20 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl ...@@ -105,20 +117,20 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
inTorque = outTorque / effectiveRatio + torqueLossResult.Value; inTorque = outTorque / effectiveRatio + torqueLossResult.Value;
} }
if (Disengaged) { if (CurrentState.Disengaged) {
return NextComponent.Initialize(0.SI<NewtonMeter>(), null); return NextComponent.Initialize(0.SI<NewtonMeter>(), null);
} }
if (!TorqueConverterLocked && !ModelData.Gears[Gear].HasTorqueConverter) { if (!CurrentState.TorqueConverterLocked && !ModelData.Gears[Gear].HasTorqueConverter) {
throw new VectoSimulationException("Torque converter requested by strategy for gear without torque converter!"); throw new VectoSimulationException("Torque converter requested by strategy for gear without torque converter!");
} }
var response = TorqueConverterLocked var response = CurrentState.TorqueConverterLocked
? NextComponent.Initialize(inTorque, inAngularVelocity) ? NextComponent.Initialize(inTorque, inAngularVelocity)
: TorqueConverter.Initialize(inTorque, inAngularVelocity); : TorqueConverter.Initialize(inTorque, inAngularVelocity);
PreviousState.SetState(inTorque, inAngularVelocity, outTorque, outAngularVelocity); PreviousState.SetState(inTorque, inAngularVelocity, outTorque, outAngularVelocity);
PreviousState.Gear = Gear; PreviousState.Gear = Gear;
PreviousState.TorqueConverterLocked = TorqueConverterLocked; PreviousState.TorqueConverterLocked = CurrentState.TorqueConverterLocked;
return response; return response;
} }
...@@ -150,7 +162,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl ...@@ -150,7 +162,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
Case<ResponseOverload>(). Case<ResponseOverload>().
Default(r => { throw new UnexpectedResponseException("AT-Gearbox.Initialize", r); }); Default(r => { throw new UnexpectedResponseException("AT-Gearbox.Initialize", r); });
return new ResponseDryRun() { return new ResponseDryRun {
Source = this, Source = this,
EngineSpeed = response.EngineSpeed, EngineSpeed = response.EngineSpeed,
EnginePowerRequest = response.EnginePowerRequest, EnginePowerRequest = response.EnginePowerRequest,
...@@ -165,29 +177,30 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl ...@@ -165,29 +177,30 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
Log.Debug("AT-Gearbox Power Request: torque: {0}, angularVelocity: {1}", outTorque, outAngularVelocity); Log.Debug("AT-Gearbox Power Request: torque: {0}, angularVelocity: {1}", outTorque, outAngularVelocity);
if ((DataBus.VehicleStopped && outAngularVelocity > 0) || (Disengaged && outTorque.IsGreater(0))) { if (!dryRun &&
((DataBus.VehicleStopped && outAngularVelocity > 0) || (CurrentState.Disengaged && outTorque.IsGreater(0)))) {
Gear = 1; //Strategy.InitGear(absTime, dt, outTorque, outAngularVelocity); Gear = 1; //Strategy.InitGear(absTime, dt, outTorque, outAngularVelocity);
TorqueConverterLocked = false; CurrentState.TorqueConverterLocked = false;
LastShift = absTime; LastShift = absTime;
Disengaged = false; CurrentState.Disengaged = false;
} }
IResponse retVal; IResponse retVal;
var count = 0; var count = 0;
var loop = false; var loop = false;
do { do {
if (Disengaged || (DataBus.DriverBehavior == DrivingBehavior.Halted)) { if (CurrentState.Disengaged || (DataBus.DriverBehavior == DrivingBehavior.Halted)) {
// only when vehicle is halted or close before halting // only when vehicle is halted or close before halting
retVal = RequestDisengaged(absTime, dt, outTorque, outAngularVelocity, dryRun); retVal = RequestDisengaged(absTime, dt, outTorque, outAngularVelocity, dryRun);
} else { } else {
Disengaged = false; CurrentState.Disengaged = false;
retVal = RequestEngaged(absTime, dt, outTorque, outAngularVelocity, dryRun); retVal = RequestEngaged(absTime, dt, outTorque, outAngularVelocity, dryRun);
IdleController.Reset(); IdleController.Reset();
} }
retVal.Switch() retVal.Switch()
.Case<ResponseGearShift>(r => { .Case<ResponseGearShift>(r => {
loop = true; loop = true;
Gear = Strategy.Engage(absTime, dt, outTorque, outAngularVelocity); Gear = _strategy.Engage(absTime, dt, outTorque, outAngularVelocity);
LastShift = absTime; LastShift = absTime;
}); });
} while (loop && ++count < 2); } while (loop && ++count < 2);
...@@ -201,7 +214,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl ...@@ -201,7 +214,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
{ {
var effectiveRatio = ModelData.Gears[Gear].Ratio; var effectiveRatio = ModelData.Gears[Gear].Ratio;
var effectiveLossMap = ModelData.Gears[Gear].LossMap; var effectiveLossMap = ModelData.Gears[Gear].LossMap;
if (!TorqueConverterLocked) { if (!CurrentState.TorqueConverterLocked) {
effectiveRatio = ModelData.Gears[Gear].TorqueConverterRatio; effectiveRatio = ModelData.Gears[Gear].TorqueConverterRatio;
effectiveLossMap = ModelData.Gears[Gear].TorqueConverterGearLossMap; effectiveLossMap = ModelData.Gears[Gear].TorqueConverterGearLossMap;
} }
...@@ -214,7 +227,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl ...@@ -214,7 +227,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
var inTorque = outTorque / effectiveRatio + inTorqueLossResult.Value; var inTorque = outTorque / effectiveRatio + inTorqueLossResult.Value;
if (!TorqueConverterLocked && !ModelData.Gears[Gear].HasTorqueConverter) { if (!CurrentState.TorqueConverterLocked && !ModelData.Gears[Gear].HasTorqueConverter) {
throw new VectoSimulationException("Torque converter requested by strategy for gear without torque converter!"); throw new VectoSimulationException("Torque converter requested by strategy for gear without torque converter!");
} }
var inAngularVelocity = outAngularVelocity * effectiveRatio; var inAngularVelocity = outAngularVelocity * effectiveRatio;
...@@ -227,14 +240,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl ...@@ -227,14 +240,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
CurrentState.SetState(inTorque, inAngularVelocity, outTorque, outAngularVelocity); CurrentState.SetState(inTorque, inAngularVelocity, outTorque, outAngularVelocity);
CurrentState.Gear = Gear; CurrentState.Gear = Gear;
CurrentState.TorqueConverterLocked = TorqueConverterLocked;
CurrentState.TransmissionTorqueLoss = inTorque - outTorque / effectiveRatio; CurrentState.TransmissionTorqueLoss = inTorque - outTorque / effectiveRatio;
if (!TorqueConverterLocked) { if (!CurrentState.TorqueConverterLocked) {
return TorqueConverter.Request(absTime, dt, inTorque, inAngularVelocity, dryRun); return TorqueConverter.Request(absTime, dt, inTorque, inAngularVelocity, dryRun);
} }
if (!dryRun && if (!dryRun &&
Strategy.ShiftRequired(absTime, dt, outTorque, outAngularVelocity, inTorque, inAngularVelocity, Gear, LastShift)) { _strategy.ShiftRequired(absTime, dt, outTorque, outAngularVelocity, inTorque, inAngularVelocity, Gear, LastShift)) {
return new ResponseGearShift() { return new ResponseGearShift() {
Source = this Source = this
}; };
...@@ -291,9 +303,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl ...@@ -291,9 +303,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
var avgInAngularSpeed = (PreviousState.InAngularVelocity + var avgInAngularSpeed = (PreviousState.InAngularVelocity +
CurrentState.InAngularVelocity) / 2.0; CurrentState.InAngularVelocity) / 2.0;
container[ModalResultField.Gear] = Disengaged || DataBus.VehicleStopped ? 0 : Gear; container[ModalResultField.Gear] = CurrentState.Disengaged || DataBus.VehicleStopped ? 0 : Gear;
container[ModalResultField.TC_Locked] = TorqueConverterLocked; container[ModalResultField.TC_Locked] = CurrentState.TorqueConverterLocked;
container[ModalResultField.P_gbx_loss] = CurrentState.TransmissionTorqueLoss * avgInAngularSpeed; container[ModalResultField.P_gbx_loss] = CurrentState.TransmissionTorqueLoss * avgInAngularSpeed;
container[ModalResultField.P_gbx_inertia] = CurrentState.InertiaTorqueLossOut * avgInAngularSpeed; container[ModalResultField.P_gbx_inertia] = CurrentState.InertiaTorqueLossOut * avgInAngularSpeed;
container[ModalResultField.P_gbx_in] = CurrentState.InTorque * avgInAngularSpeed; container[ModalResultField.P_gbx_in] = CurrentState.InTorque * avgInAngularSpeed;
...@@ -301,8 +312,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl ...@@ -301,8 +312,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
protected override void DoCommitSimulationStep() protected override void DoCommitSimulationStep()
{ {
if (!Disengaged) { if (!CurrentState.Disengaged && CurrentState.TorqueLossResult != null && CurrentState.TorqueLossResult.Extrapolated) {
if (CurrentState.TorqueLossResult != null && CurrentState.TorqueLossResult.Extrapolated) {
Log.Warn( Log.Warn(
"Gear {0} LossMap data was extrapolated: range for loss map is not sufficient: n:{1}, torque:{2}, ratio:{3}", "Gear {0} LossMap data was extrapolated: range for loss map is not sufficient: n:{1}, torque:{2}, ratio:{3}",
Gear, CurrentState.OutAngularVelocity.ConvertTo().Rounds.Per.Minute, CurrentState.OutTorque, Gear, CurrentState.OutAngularVelocity.ConvertTo().Rounds.Per.Minute, CurrentState.OutTorque,
...@@ -314,27 +324,20 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl ...@@ -314,27 +324,20 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
ModelData.Gears[Gear].Ratio); ModelData.Gears[Gear].Ratio);
} }
} }
}
if (DataBus.VehicleStopped) { if (DataBus.VehicleStopped) {
Disengaged = true; CurrentState.Disengaged = true;
} }
AdvanceState(); AdvanceState();
}
public override bool ClutchClosed(Second absTime) CurrentState.TorqueConverterLocked = PreviousState.TorqueConverterLocked;
{ CurrentState.Disengaged = PreviousState.Disengaged;
return true;
} }
public class ATGearboxState : GearboxState public class ATGearboxState : GearboxState
{ {
public bool TorqueConverterLocked; public bool TorqueConverterLocked;
public bool Disengaged = true;
//public PerSecond TorqueConverterTorqueOut;
//public PerSecond TorqueConverterAngularSpeedOut;
//public double TorqueConverterSpeedRatio;
//public double TorqueConverterTorqueRatio;
} }
} }
} }
\ No newline at end of file
...@@ -112,9 +112,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl ...@@ -112,9 +112,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
return false; return false;
} }
// _ -> 1C: if n_eng == 0 // L -> 0: disengage if inAngularVelocity == 0
if (_gearbox.TorqueConverterLocked && inAngularVelocity.IsEqual(0.SI<PerSecond>())) { if (_gearbox.TorqueConverterLocked && inAngularVelocity.IsEqual(0.SI<PerSecond>())) {
NextGear.SetState(absTime, false, 1, false); NextGear.SetState(absTime, true, 1, false);
return true; return true;
} }
......
...@@ -248,7 +248,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl ...@@ -248,7 +248,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
maxTorque = VectoMath.Min(maxTorque, gearboxFullLoad); maxTorque = VectoMath.Min(maxTorque, gearboxFullLoad);
} }
CurrentState.EngineTorque = totalTorqueDemand.Limit(minTorque, maxTorque); CurrentState.EngineTorque = totalTorqueDemand.LimitTo(minTorque, maxTorque);
CurrentState.EnginePower = CurrentState.EngineTorque * avgEngineSpeed; CurrentState.EnginePower = CurrentState.EngineTorque * avgEngineSpeed;
if (totalTorqueDemand.IsGreater(0) && if (totalTorqueDemand.IsGreater(0) &&
......
...@@ -364,18 +364,18 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl ...@@ -364,18 +364,18 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
private TorqueConverterOperatingPoint FindOperatingPoint(NewtonMeter outTorque, private TorqueConverterOperatingPoint FindOperatingPoint(NewtonMeter outTorque,
PerSecond outAngularVelocity) PerSecond outAngularVelocity)
{ {
try {
var operatingPointList = TorqueConverter.FindOperatingPoint(outTorque, outAngularVelocity, DataBus.EngineIdleSpeed); var operatingPointList = TorqueConverter.FindOperatingPoint(outTorque, outAngularVelocity, DataBus.EngineIdleSpeed);
if (operatingPointList.Count == 0) {
Log.Debug("CycleGearbox: Failed to find torque converter operating point, fallback: creeping");
var tqOperatingPoint = TorqueConverter.FindOperatingPoint(DataBus.EngineIdleSpeed, outAngularVelocity);
return tqOperatingPoint;
}
var operatingPoint = SelectOperatingPoint(operatingPointList); var operatingPoint = SelectOperatingPoint(operatingPointList);
if (operatingPoint.InAngularVelocity.IsGreater(DataBus.EngineRatedSpeed)) { if (operatingPoint.InAngularVelocity.IsGreater(DataBus.EngineRatedSpeed)) {
operatingPoint = TorqueConverter.FindOperatingPoint(DataBus.EngineRatedSpeed, outAngularVelocity); operatingPoint = TorqueConverter.FindOperatingPoint(DataBus.EngineRatedSpeed, outAngularVelocity);
} }
return operatingPoint; return operatingPoint;
} catch (VectoException ve) {
Log.Debug(ve, "failed to find torque converter operating point, fallback: creeping");
var tqOperatingPoint = TorqueConverter.FindOperatingPoint(DataBus.EngineIdleSpeed, outAngularVelocity);
return tqOperatingPoint;
}
} }
private TorqueConverterOperatingPoint SelectOperatingPoint(IList<TorqueConverterOperatingPoint> operatingPointList) private TorqueConverterOperatingPoint SelectOperatingPoint(IList<TorqueConverterOperatingPoint> operatingPointList)
......
...@@ -82,21 +82,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl ...@@ -82,21 +82,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
return retVal; return retVal;
} }
public IResponse Request(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, public IResponse Request(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity,
bool dryRun = false) bool dryRun = false)
{ {
if (dryRun) { if (dryRun) {
var dryOperatingPoint = FindOperatingPoint(outTorque, outAngularVelocity); var dryOperatingPoint = FindOperatingPoint(outTorque, outAngularVelocity);
var engineResponse = var engineResponse = (ResponseDryRun)
(ResponseDryRun)NextComponent.Request(absTime, dt, dryOperatingPoint.InTorque, dryOperatingPoint.InAngularVelocity, NextComponent.Request(absTime, dt, dryOperatingPoint.InTorque, dryOperatingPoint.InAngularVelocity, true);
true);
var deltaTorqueConverter = (outTorque - dryOperatingPoint.OutTorque) *
(PreviousState.OutAngularVelocity + dryOperatingPoint.OutAngularVelocity) / 2.0;
var deltaEngine = (engineResponse.DeltaFullLoad > 0 ? engineResponse.DeltaFullLoad : 0.SI<Watt>()) +
(engineResponse.DeltaDragLoad < 0 ? -engineResponse.DeltaDragLoad : 0.SI<Watt>());
dryOperatingPoint = outTorque.IsGreater(0) && DataBus.BrakePower.IsEqual(0) dryOperatingPoint = outTorque.IsGreater(0) && DataBus.BrakePower.IsEqual(0)
? GetMaxPowerOperatingPoint(dt, outAngularVelocity, engineResponse) ? GetMaxPowerOperatingPoint(dt, outAngularVelocity, engineResponse)
...@@ -104,10 +96,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl ...@@ -104,10 +96,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
engineResponse = (ResponseDryRun)NextComponent.Request(absTime, dt, dryOperatingPoint.InTorque, engineResponse = (ResponseDryRun)NextComponent.Request(absTime, dt, dryOperatingPoint.InTorque,
dryOperatingPoint.InAngularVelocity, true); dryOperatingPoint.InAngularVelocity, true);
var delta = (outTorque - dryOperatingPoint.OutTorque) * var delta = (outTorque - dryOperatingPoint.OutTorque) *
(PreviousState.OutAngularVelocity + dryOperatingPoint.OutAngularVelocity) / 2.0; (PreviousState.OutAngularVelocity + dryOperatingPoint.OutAngularVelocity) / 2.0;
//deltaTorqueConverter.Value() * (deltaEngine.IsEqual(0) ? 1 : deltaEngine.Value());
return new ResponseDryRun() { return new ResponseDryRun() {
Source = this, Source = this,
DeltaFullLoad = delta, DeltaFullLoad = delta,
...@@ -182,8 +173,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl ...@@ -182,8 +173,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
protected internal TorqueConverterOperatingPoint FindOperatingPoint(NewtonMeter outTorque, protected internal TorqueConverterOperatingPoint FindOperatingPoint(NewtonMeter outTorque,
PerSecond outAngularVelocity) PerSecond outAngularVelocity)
{ {
try {
var operatingPointList = ModelData.FindOperatingPoint(outTorque, outAngularVelocity, DataBus.EngineIdleSpeed); var operatingPointList = ModelData.FindOperatingPoint(outTorque, outAngularVelocity, DataBus.EngineIdleSpeed);
if (operatingPointList.Count == 0) {
Log.Debug("TorqueConverter: Failed to find torque converter operating point, fallback: creeping");
var tqOperatingPoint = ModelData.FindOperatingPoint(DataBus.EngineIdleSpeed, outAngularVelocity);
return tqOperatingPoint;
}
var operatingPoint = SelectOperatingPoint(operatingPointList); var operatingPoint = SelectOperatingPoint(operatingPointList);
if (operatingPoint.InAngularVelocity.IsSmaller(DataBus.EngineIdleSpeed)) { if (operatingPoint.InAngularVelocity.IsSmaller(DataBus.EngineIdleSpeed)) {
throw new VectoException("Invalid operating point, inAngularVelocity below engine's idle speed: {0}", throw new VectoException("Invalid operating point, inAngularVelocity below engine's idle speed: {0}",
...@@ -193,28 +189,25 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl ...@@ -193,28 +189,25 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
operatingPoint = ModelData.FindOperatingPoint(DataBus.EngineRatedSpeed, outAngularVelocity); operatingPoint = ModelData.FindOperatingPoint(DataBus.EngineRatedSpeed, outAngularVelocity);
} }
return operatingPoint; return operatingPoint;
} catch (VectoException ve) {
Log.Debug(ve, "failed to find torque converter operating point, fallback: creeping");
var tqOperatingPoint = ModelData.FindOperatingPoint(DataBus.EngineIdleSpeed, outAngularVelocity);
return tqOperatingPoint;
}
} }
private TorqueConverterOperatingPoint SelectOperatingPoint(IList<TorqueConverterOperatingPoint> operatingPointList) private TorqueConverterOperatingPoint SelectOperatingPoint(IList<TorqueConverterOperatingPoint> operatingPointList)
{ {
if (operatingPointList.Count == 1) { if (operatingPointList.Count == 1) {
return operatingPointList[0]; return operatingPointList[0];
} }
var filtered = operatingPointList.Where(x => var filtered = operatingPointList.Where(x =>
(x.InTorque * x.InAngularVelocity).IsSmallerOrEqual(DataBus.EngineStationaryFullPower(x.InAngularVelocity), (x.InTorque * x.InAngularVelocity).IsSmallerOrEqual(DataBus.EngineStationaryFullPower(x.InAngularVelocity),
Constants.SimulationSettings.LineSearchTolerance.SI<Watt>()) && Constants.SimulationSettings.LineSearchTolerance.SI<Watt>()) &&
(x.InTorque * x.InAngularVelocity).IsGreaterOrEqual(DataBus.EngineDragPower(x.InAngularVelocity), (x.InTorque * x.InAngularVelocity).IsGreaterOrEqual(DataBus.EngineDragPower(x.InAngularVelocity),
Constants.SimulationSettings.LineSearchTolerance.SI<Watt>()) Constants.SimulationSettings.LineSearchTolerance.SI<Watt>())
).ToArray(); ).ToList();
if (filtered.Count() == 1) {
if (filtered.Count == 1) {
return filtered.First(); return filtered.First();
} }
return operatingPointList[0]; return operatingPointList[0];
} }
......
...@@ -94,7 +94,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl ...@@ -94,7 +94,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
CurrentState.SimulationInterval = dt; CurrentState.SimulationInterval = dt;
CurrentState.Acceleration = acceleration; CurrentState.Acceleration = acceleration;
CurrentState.Velocity = PreviousState.Velocity + acceleration * dt; CurrentState.Velocity = PreviousState.Velocity + acceleration * dt;
if (CurrentState.Velocity.IsSmallerOrEqual(0.SI<MeterPerSecond>(), if (CurrentState.Velocity.IsEqual(0.SI<MeterPerSecond>(),
Constants.SimulationSettings.VehicleSpeedHaltTolerance)) { Constants.SimulationSettings.VehicleSpeedHaltTolerance)) {
CurrentState.Velocity = 0.SI<MeterPerSecond>(); CurrentState.Velocity = 0.SI<MeterPerSecond>();
} }
......
...@@ -109,6 +109,7 @@ ...@@ -109,6 +109,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Configuration\Constants.cs" /> <Compile Include="Configuration\Constants.cs" />
<Compile Include="InputData\AuxiliaryFileHelper.cs" />
<Compile Include="InputData\FileIO\JSON\JSONComponentInputData.cs" /> <Compile Include="InputData\FileIO\JSON\JSONComponentInputData.cs" />
<Compile Include="InputData\FileIO\JSON\JsonExtensionMethods.cs" /> <Compile Include="InputData\FileIO\JSON\JsonExtensionMethods.cs" />
<Compile Include="InputData\Impl\InputData.cs" /> <Compile Include="InputData\Impl\InputData.cs" />
......
...@@ -29,11 +29,15 @@ ...@@ -29,11 +29,15 @@
* Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology * Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology
*/ */
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using TUGraz.VectoCommon.Exceptions; using TUGraz.VectoCommon.Exceptions;
using TUGraz.VectoCommon.InputData;
using TUGraz.VectoCommon.Models; using TUGraz.VectoCommon.Models;
using TUGraz.VectoCommon.Utils; using TUGraz.VectoCommon.Utils;
using TUGraz.VectoCore.InputData;
using TUGraz.VectoCore.InputData.FileIO.JSON; using TUGraz.VectoCore.InputData.FileIO.JSON;
using TUGraz.VectoCore.InputData.Impl;
using TUGraz.VectoCore.InputData.Reader; using TUGraz.VectoCore.InputData.Reader;
using TUGraz.VectoCore.InputData.Reader.ComponentData; using TUGraz.VectoCore.InputData.Reader.ComponentData;
using TUGraz.VectoCore.Models.Declaration; using TUGraz.VectoCore.Models.Declaration;
...@@ -193,7 +197,14 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation ...@@ -193,7 +197,14 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation
var aux = new EngineAuxiliary(container); var aux = new EngineAuxiliary(container);
var auxData = AuxiliaryDataReader.ReadFromFile(@"TestData\Components\24t_Coach_ALT.vaux", "ALT"); var auxDataInputData = new AuxiliaryDataInputData {
ID = "ALT1",
Type = AuxiliaryType.ElectricSystem,
Technology = new List<string>(),
};
AuxiliaryFileHelper.FillAuxiliaryDataInputData(auxDataInputData, @"TestData\Components\24t_Coach_ALT.vaux");
var auxData = AuxiliaryDataReader.Create(auxDataInputData);
// ratio = 4.078 // ratio = 4.078
// efficiency_engine = 0.96 // efficiency_engine = 0.96
// efficiency_supply = 0.98 // efficiency_supply = 0.98
...@@ -252,7 +263,14 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation ...@@ -252,7 +263,14 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation
var aux = new EngineAuxiliary(container); var aux = new EngineAuxiliary(container);
var auxData = AuxiliaryDataReader.ReadFromFile(@"TestData\Components\24t_Coach_ALT.vaux", "ALT"); var auxDataInputData = new AuxiliaryDataInputData {
ID = "ALT1",
Type = AuxiliaryType.ElectricSystem,
Technology = new List<string>(),
};
AuxiliaryFileHelper.FillAuxiliaryDataInputData(auxDataInputData, @"TestData\Components\24t_Coach_ALT.vaux");
var auxData = AuxiliaryDataReader.Create(auxDataInputData);
// ratio = 4.078 // ratio = 4.078
// efficiency_engine = 0.96 // efficiency_engine = 0.96
// efficiency_supply = 0.98 // efficiency_supply = 0.98
...@@ -303,8 +321,10 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation ...@@ -303,8 +321,10 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation
[TestMethod] [TestMethod]
public void AuxFileMissing() public void AuxFileMissing()
{ {
AssertHelper.Exception<VectoException>(() => AuxiliaryDataReader.ReadFromFile(@"NOT_EXISTING_AUX_FILE.vaux", "N.A."), AssertHelper.Exception<VectoException>(() => {
"Auxiliary file not found: NOT_EXISTING_AUX_FILE.vaux"); var auxDataInputData = new AuxiliaryDataInputData();
AuxiliaryFileHelper.FillAuxiliaryDataInputData(auxDataInputData, @"NOT_EXISTING_AUX_FILE.vaux");
}, "Auxiliary file not found: NOT_EXISTING_AUX_FILE.vaux");
} }
[TestMethod] [TestMethod]
......
...@@ -58,7 +58,6 @@ namespace TUGraz.VectoCore.Tests.Utils ...@@ -58,7 +58,6 @@ namespace TUGraz.VectoCore.Tests.Utils
Assert.AreEqual(positive, VectoMath.Abs(negative)); Assert.AreEqual(positive, VectoMath.Abs(negative));
Assert.AreEqual(positive, VectoMath.Abs(positive)); Assert.AreEqual(positive, VectoMath.Abs(positive));
var smallerWatt = 0.SI<Watt>(); var smallerWatt = 0.SI<Watt>();
var biggerWatt = 5.SI<Watt>(); var biggerWatt = 5.SI<Watt>();
var negativeWatt = -10.SI<Watt>(); var negativeWatt = -10.SI<Watt>();
...@@ -68,12 +67,10 @@ namespace TUGraz.VectoCore.Tests.Utils ...@@ -68,12 +67,10 @@ namespace TUGraz.VectoCore.Tests.Utils
Assert.AreEqual(biggerWatt, VectoMath.Max(smallerWatt, biggerWatt)); Assert.AreEqual(biggerWatt, VectoMath.Max(smallerWatt, biggerWatt));
Assert.AreEqual(positiveWatt, VectoMath.Abs(negativeWatt)); Assert.AreEqual(positiveWatt, VectoMath.Abs(negativeWatt));
Assert.AreEqual(positiveWatt, VectoMath.Abs(positiveWatt)); Assert.AreEqual(positiveWatt, VectoMath.Abs(positiveWatt));
} }
[TestCase(0, -1, 0, 1, -1, 0, 1, 0, 0, 0), [TestCase(0, -1, 0, 1, -1, 0, 1, 0, 0, 0),
TestCase(0, 0, 10, 0, 0, 5, 10, 5, double.NaN, double.NaN), TestCase(0, 0, 10, 0, 0, 5, 10, 5, double.NaN, double.NaN),
TestCase(0, 0, 0, 10, 5, 0, 10, 5, double.NaN, double.NaN), TestCase(0, 0, 0, 10, 5, 0, 10, 5, double.NaN, double.NaN),
...@@ -101,10 +98,10 @@ namespace TUGraz.VectoCore.Tests.Utils ...@@ -101,10 +98,10 @@ namespace TUGraz.VectoCore.Tests.Utils
{ {
var results = VectoMath.CubicEquationSolver(a, b, c, d); var results = VectoMath.CubicEquationSolver(a, b, c, d);
Assert.AreEqual(expected.Length, results.Count); Assert.AreEqual(expected.Length, results.Length);
var sorted = expected.ToList(); var sorted = expected.ToList();
sorted.Sort(); sorted.Sort();
results.Sort(); Array.Sort(results);
var comparison = sorted.Zip(results, (exp, result) => exp - result); var comparison = sorted.Zip(results, (exp, result) => exp - result);
foreach (var cmp in comparison) { foreach (var cmp in comparison) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment