From 104cd4fb441ef3f4dd63305d4cf3b8d2420054f8 Mon Sep 17 00:00:00 2001
From: Markus Quaritsch <markus.quaritsch@tugraz.at>
Date: Thu, 12 Nov 2020 18:24:35 +0100
Subject: [PATCH] adding missing files: gearshift position  and shiftlineset
 (Effshift AT), formerly part of Voith shift strategy

---
 .../VectoCommon/Models/GearshiftPosition.cs   | 188 ++++++++++++++++++
 .../SimulationComponent/Impl/ShiftLineSet.cs  |  71 +++++++
 2 files changed, 259 insertions(+)
 create mode 100644 VectoCommon/VectoCommon/Models/GearshiftPosition.cs
 create mode 100644 VectoCore/VectoCore/Models/SimulationComponent/Impl/ShiftLineSet.cs

diff --git a/VectoCommon/VectoCommon/Models/GearshiftPosition.cs b/VectoCommon/VectoCommon/Models/GearshiftPosition.cs
new file mode 100644
index 0000000000..d6a1efce27
--- /dev/null
+++ b/VectoCommon/VectoCommon/Models/GearshiftPosition.cs
@@ -0,0 +1,188 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Security.Cryptography;
+
+namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
+{
+	[DebuggerDisplay("{Name}")]
+	public class GearshiftPosition
+	{
+		public uint Gear { get; }
+		public bool? TorqueConverterLocked { get; }
+
+		public GearshiftPosition(uint gear, bool? torqueConverterLocked = null)
+		{
+			Gear = gear;
+			TorqueConverterLocked = torqueConverterLocked;
+		}
+
+		public override string ToString()
+		{
+			return Name;
+		}
+
+		public string Name
+		{
+			get {
+				return $"{Gear}{(Gear == 0 ? "" : (TorqueConverterLocked.HasValue ? (TorqueConverterLocked.Value ? "L" : "C") : ""))}";
+			}
+		}
+
+		public bool Engaged
+		{
+			get { return Gear != 0; }
+		}
+
+		public override bool Equals(object x)
+		{
+			var other = x as GearshiftPosition;
+			if (other == null)
+				return false;
+
+			return other.Gear == Gear && other.TorqueConverterLocked == TorqueConverterLocked;
+		}
+
+		public override int GetHashCode()
+		{
+			return Name.GetHashCode();
+		}
+
+		public static bool operator >(GearshiftPosition p1, GearshiftPosition p2)
+		{
+			if (p1.Gear > p2.Gear) {
+				return true;
+			}
+
+			if (p1.Gear != p2.Gear) {
+				return false;
+			}
+
+			if (!p1.TorqueConverterLocked.HasValue || !p2.TorqueConverterLocked.HasValue) {
+				return false;
+			}
+
+			return p1.TorqueConverterLocked.Value && !p2.TorqueConverterLocked.Value;
+		}
+
+		public static bool operator <(GearshiftPosition p1, GearshiftPosition p2)
+		{
+			if (p1.Gear < p2.Gear) {
+				return true;
+			}
+
+			if (p1.Gear != p2.Gear) {
+				return false;
+			}
+
+			if (!p1.TorqueConverterLocked.HasValue || !p2.TorqueConverterLocked.HasValue) {
+				return false;
+			}
+
+			return  p2.TorqueConverterLocked.Value && !p1.TorqueConverterLocked.Value;
+		}
+
+		
+	}
+
+	public class GearList :IEnumerable<GearshiftPosition>
+	{
+		protected GearshiftPosition[] Entries;
+
+		public GearList(GearshiftPosition[] gearList)
+		{
+			Entries = gearList;
+		}
+
+		public bool HasPredecessor(GearshiftPosition cur)
+		{
+			var idx = Array.IndexOf(Entries, cur);
+			return idx > 0;
+		}
+
+
+		public GearshiftPosition Predecessor(GearshiftPosition cur)
+		{
+			var idx = Array.IndexOf(Entries, cur);
+			
+			return idx <= 0 ? null : Entries[idx - 1];
+		}
+
+		public bool HasSuccessor(GearshiftPosition cur)
+        {
+			var idx = Array.IndexOf(Entries, cur);
+			return idx < Entries.Length - 1;
+		}
+
+		public GearshiftPosition Successor(GearshiftPosition cur)
+		{
+			var idx = Array.IndexOf(Entries, cur);
+
+			return idx < 0 || idx >= Entries.Length - 1 ? null : Entries[idx + 1];
+		}
+
+		public GearshiftPosition Successor(GearshiftPosition cur, uint numUp)
+		{
+			var idx = Array.IndexOf(Entries, cur);
+
+			if (idx < 0) {
+				return null;
+			}
+
+			var next = idx + numUp;
+
+			return next >= Entries.Length ? Entries.Last() : Entries[next];
+		}
+
+		public GearshiftPosition Predecessor(GearshiftPosition cur, uint numDown)
+		{
+			var idx = Array.IndexOf(Entries, cur);
+
+			if (idx < 0) {
+				return null;
+			}
+
+			var next = idx - numDown;
+
+			return next < 0 ? Entries.First() : Entries[next];
+		}
+
+		public IEnumerator<GearshiftPosition> GetEnumerator()
+		{
+			foreach (var entry in Entries) {
+				yield return entry;
+			}
+		}
+
+		IEnumerator IEnumerable.GetEnumerator()
+		{
+			return GetEnumerator();
+		}
+
+		public int Distance(GearshiftPosition from, GearshiftPosition to)
+		{
+			var startIdx = Array.IndexOf(Entries, from);
+			var endIdx = Array.IndexOf(Entries, to);
+			return startIdx - endIdx;
+		}
+
+
+		public IEnumerable<GearshiftPosition> IterateGears(GearshiftPosition from, GearshiftPosition to)
+		{
+			var startIdx = Array.IndexOf(Entries, from);
+			var endIdx = Array.IndexOf(Entries, to);
+
+			if (endIdx > startIdx) {
+				for (var i = startIdx; i <= endIdx; i++) {
+					yield return Entries[i];
+				}
+			} else {
+				for (var i = startIdx; i >= endIdx; i--) {
+					yield return Entries[i];
+				}
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/ShiftLineSet.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/ShiftLineSet.cs
new file mode 100644
index 0000000000..1d14796f0d
--- /dev/null
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/ShiftLineSet.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+using TUGraz.VectoCommon.Exceptions;
+using TUGraz.VectoCommon.Utils;
+
+namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
+{
+	public class ShiftLineSet
+	{
+		public const double DownhillSlope = -5;
+		public const double UphillSlope = 5;
+
+		public Dictionary<int, ShiftLines> LoadStages = new Dictionary<int, ShiftLines>();
+
+		public PerSecond LookupShiftSpeed(
+			int loadStage, Radian gradient, MeterPerSquareSecond acceleration, MeterPerSquareSecond aMin,
+			MeterPerSquareSecond aMax)
+		{
+			if (!LoadStages.ContainsKey(loadStage)) {
+				throw new VectoException("No Shiftlines for load stage {0} found", loadStage);
+			}
+
+			var shiftLinesSet = LoadStages[loadStage];
+
+			//var slope = (Math.Tan(gradient.Value()) * 100).LimitTo(
+			//	ATShiftStrategyVoith.DownhillSlope, ATShiftStrategyVoith.UphillSlope);
+
+			gradient = gradient.LimitTo(
+				VectoMath.InclinationToAngle(DownhillSlope),
+				VectoMath.InclinationToAngle(UphillSlope));
+			var shiftLine = shiftLinesSet.LookupShiftSpeed(gradient);
+			var acc = aMin > aMax ? acceleration.LimitTo(aMax, aMin) : acceleration.LimitTo(aMin, aMax);
+
+			var shiftSpeed = VectoMath.Interpolate(
+				aMin, aMax, shiftLine.ShiftSpeedAMin, shiftLine.ShiftSpeedAMax, acc);
+
+			return shiftSpeed;
+		}
+	}
+
+	public class ShiftLines
+	{
+
+		internal readonly List<Tuple<Radian, PerSecond>> entriesAMin = new List<Tuple<Radian, PerSecond>>();
+		internal readonly List<Tuple<Radian, PerSecond>> entriesAMax = new List<Tuple<Radian, PerSecond>>();
+
+
+		public ShiftSpeedTuple LookupShiftSpeed(Radian gradent)
+		{
+			var sectLow = entriesAMin.GetSection(x => x.Item1 < gradent);
+			var sectHigh = entriesAMax.GetSection(x => x.Item1 < gradent);
+
+			return new ShiftSpeedTuple(
+				VectoMath.Interpolate(sectLow.Item1.Item1, sectLow.Item2.Item1, sectLow.Item1.Item2, sectLow.Item2.Item2, gradent),
+				VectoMath.Interpolate(
+					sectHigh.Item1.Item1, sectHigh.Item2.Item1, sectHigh.Item1.Item2, sectHigh.Item2.Item2, gradent));
+		}
+	}
+
+	public class ShiftSpeedTuple
+	{
+		public PerSecond ShiftSpeedAMin { get; }
+		public PerSecond ShiftSpeedAMax { get; }
+
+		public ShiftSpeedTuple(PerSecond shiftSpeedAMin, PerSecond shiftSpeedAMax)
+		{
+			ShiftSpeedAMin = shiftSpeedAMin;
+			ShiftSpeedAMax = shiftSpeedAMax;
+		}
+	}
+}
\ No newline at end of file
-- 
GitLab