From 1974de1f4c73727057cd881fe072a6095e0808dc Mon Sep 17 00:00:00 2001
From: Markus Quaritsch <markus.quaritsch@tugraz.at>
Date: Mon, 17 Jun 2019 14:45:17 +0200
Subject: [PATCH] adding input parameter to allow sikipping gears with FC-based
 shift approach (AMT)

---
 VECTO/Input Files/Gearbox.vb                  |   8 +-
 .../InputData/EngineeringInputData.cs         |   2 +
 .../InputData/FileIO/JSON/JSONGearboxData.cs  |   1 +
 .../InputData/FileIO/JSON/JSONTCUData.cs      |  11 ++
 .../XMLEngineeringGearshiftData.cs            |   1 +
 .../DeclarationDataAdapter.cs                 |   1 +
 .../EngineeringDataAdapter.cs                 |   1 +
 .../Data/ShiftStrategyParameters.cs           |   2 +
 .../Impl/AMTShiftStrategyOptimized.cs         | 113 ++++++++++++++----
 .../Models/Simulation/ShiftStrategyV2Test.cs  |   4 +-
 .../Class5_Tractor_ENG_FC.vecto               |  45 +++++++
 .../Class5_Tractor_4x2/ShiftParameters.vtcu   |   5 +
 12 files changed, 167 insertions(+), 27 deletions(-)
 create mode 100644 VectoCore/VectoCoreTest/TestData/Integration/ShiftStrategyV2/Class5_Tractor_4x2/Class5_Tractor_ENG_FC.vecto

diff --git a/VECTO/Input Files/Gearbox.vb b/VECTO/Input Files/Gearbox.vb
index 5a56e98022..d4f8857fed 100644
--- a/VECTO/Input Files/Gearbox.vb	
+++ b/VECTO/Input Files/Gearbox.vb	
@@ -589,7 +589,13 @@ Public Class Gearbox
 		End Get
 	End Property
 
-	Public Overridable ReadOnly Property LoadStageShiftLines As TableData Implements IGearshiftEngineeringInputData.LoadStageShiftLines
+    Public ReadOnly Property AllowedGearRangeFC As Integer? Implements IGearshiftEngineeringInputData.AllowedGearRangeFC
+    get
+            Return Nothing
+    End Get
+    End Property
+
+    Public Overridable ReadOnly Property LoadStageShiftLines As TableData Implements IGearshiftEngineeringInputData.LoadStageShiftLines
 		Get
 			Return Nothing
 		End Get
diff --git a/VectoCommon/VectoCommon/InputData/EngineeringInputData.cs b/VectoCommon/VectoCommon/InputData/EngineeringInputData.cs
index 666a1156ca..904adaed18 100644
--- a/VectoCommon/VectoCommon/InputData/EngineeringInputData.cs
+++ b/VectoCommon/VectoCommon/InputData/EngineeringInputData.cs
@@ -275,6 +275,8 @@ namespace TUGraz.VectoCommon.InputData
 		double? RatioEarlyUpshiftFC { get; }
 		double? RatioEarlyDownshiftFC { get; }
 
+		int? AllowedGearRangeFC { get; }
+
 
 		// Voith GS Parameters
 		TableData LoadStageShiftLines { get; }
diff --git a/VectoCore/VectoCore/InputData/FileIO/JSON/JSONGearboxData.cs b/VectoCore/VectoCore/InputData/FileIO/JSON/JSONGearboxData.cs
index 57da0b3d22..ed8f182f2f 100644
--- a/VectoCore/VectoCore/InputData/FileIO/JSON/JSONGearboxData.cs
+++ b/VectoCore/VectoCore/InputData/FileIO/JSON/JSONGearboxData.cs
@@ -402,6 +402,7 @@ namespace TUGraz.VectoCore.InputData.FileIO.JSON
 		public MeterPerSquareSecond DriverAccelerationThresholdLow { get { return null; } }
 		public double? RatioEarlyUpshiftFC { get { return null; } }
 		public double? RatioEarlyDownshiftFC { get { return null; } }
+		public int? AllowedGearRangeFC { get { return null; } }
 		public TableData LoadStageShiftLines { get { return null; } }
 		public IList<double> LoadStageThresoldsUp { get { return null; } }
 		public IList<double> LoadStageThresoldsDown { get { return null; } }
diff --git a/VectoCore/VectoCore/InputData/FileIO/JSON/JSONTCUData.cs b/VectoCore/VectoCore/InputData/FileIO/JSON/JSONTCUData.cs
index 1da6ce8440..27137603b4 100644
--- a/VectoCore/VectoCore/InputData/FileIO/JSON/JSONTCUData.cs
+++ b/VectoCore/VectoCore/InputData/FileIO/JSON/JSONTCUData.cs
@@ -257,6 +257,17 @@ namespace TUGraz.VectoCore.InputData.FileIO.JSON
 			}
 		}
 
+		public int? AllowedGearRangeFC
+		{
+			get {
+				if (Body["AllowedGearRangeFC"] == null) {
+					return null;
+				}
+
+				return Body.GetEx<int>("AllowedGearRangeFC");
+			}
+		}
+
 		public TableData LoadStageShiftLines
 		{
 			get {
diff --git a/VectoCore/VectoCore/InputData/FileIO/XML/Engineering/DataProvider/XMLEngineeringGearshiftData.cs b/VectoCore/VectoCore/InputData/FileIO/XML/Engineering/DataProvider/XMLEngineeringGearshiftData.cs
index c2a51b2c39..4082f78c39 100644
--- a/VectoCore/VectoCore/InputData/FileIO/XML/Engineering/DataProvider/XMLEngineeringGearshiftData.cs
+++ b/VectoCore/VectoCore/InputData/FileIO/XML/Engineering/DataProvider/XMLEngineeringGearshiftData.cs
@@ -114,6 +114,7 @@ namespace TUGraz.VectoCore.InputData.FileIO.XML.Engineering.DataProvider
 		public virtual MeterPerSquareSecond DriverAccelerationThresholdLow { get { return null; } }
 		public virtual double? RatioEarlyUpshiftFC { get { return null; } }
 		public virtual double? RatioEarlyDownshiftFC { get { return null; } }
+		public int? AllowedGearRangeFC { get { return null; } }
 		public virtual TableData LoadStageShiftLines { get { return null; } }
 		public virtual IList<double> LoadStageThresoldsUp { get { return null; } }
 		public virtual IList<double> LoadStageThresoldsDown { get { return null; } }
diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapter.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapter.cs
index 2e0ddd12a8..0be1506084 100644
--- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapter.cs
+++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapter.cs
@@ -592,6 +592,7 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter
 				//--------------------
 				RatioEarlyUpshiftFC = 8.0 / axleRatio,
 				RatioEarlyDownshiftFC = 21.0 / axleRatio,
+				AllowedGearRangeFC = 1,
 			};
 
 			return retVal;
diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/EngineeringDataAdapter.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/EngineeringDataAdapter.cs
index d965ba1683..bae5ed8f90 100644
--- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/EngineeringDataAdapter.cs
+++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/EngineeringDataAdapter.cs
@@ -455,6 +455,7 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter
 				//---------------
 				RatioEarlyUpshiftFC = gsInputData.RatioEarlyUpshiftFC / axleRatio ?? 0,
 				RatioEarlyDownshiftFC = gsInputData.RatioEarlyDownshiftFC / axleRatio ?? 0,
+				AllowedGearRangeFC = gsInputData.AllowedGearRangeFC ?? 1,
 
 				// voith gs parameters
 
diff --git a/VectoCore/VectoCore/Models/Simulation/Data/ShiftStrategyParameters.cs b/VectoCore/VectoCore/Models/Simulation/Data/ShiftStrategyParameters.cs
index 78f2c7e768..86ce5e14db 100644
--- a/VectoCore/VectoCore/Models/Simulation/Data/ShiftStrategyParameters.cs
+++ b/VectoCore/VectoCore/Models/Simulation/Data/ShiftStrategyParameters.cs
@@ -58,5 +58,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Data {
 		public TableData GearshiftLines { get; set; }
 
 		public IEnumerable<Tuple<double, double>> LoadstageThresholds { get; set; }
+		
+		public int AllowedGearRangeFC { get; set; }
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/AMTShiftStrategyOptimized.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/AMTShiftStrategyOptimized.cs
index 297b73e747..1760ad0331 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/AMTShiftStrategyOptimized.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/AMTShiftStrategyOptimized.cs
@@ -44,6 +44,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			if (TestContainerGbx == null) {
 				throw new VectoException("Unknown gearboxtype: {0}", TestContainer.GearboxCtl.GetType().FullName);
 			}
+
+			if (shiftStrategyParameters.AllowedGearRangeFC > 2 || shiftStrategyParameters.AllowedGearRangeFC < 1) {
+				Log.Warn("Gear-range for FC-based gearshift must be either 1 or 2!");
+				shiftStrategyParameters.AllowedGearRangeFC = shiftStrategyParameters.AllowedGearRangeFC.LimitTo(1, 2);
+			}
 		}
 
 		#region Overrides of AMTShiftStrategy
@@ -51,8 +56,55 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		protected override uint CheckEarlyUpshift(
 			Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, uint currentGear)
 		{
-			if (ModelData.Gears[currentGear + 1].Ratio < shiftStrategyParameters.RatioEarlyUpshiftFC) {
-				return OverdriveUpshift(absTime, dt, outTorque, outAngularVelocity, currentGear);
+			var minFcGear = currentGear;
+			var minFc = double.MaxValue;
+			KilogramPerSecond fcCurrent = null;
+
+			for (var i = 1; i <= shiftStrategyParameters.AllowedGearRangeFC; i++) {
+				var tryNextGear = (uint)(currentGear + i);
+
+				if (tryNextGear >= ModelData.Gears.Keys.Max() || !(ModelData.Gears[tryNextGear].Ratio < shiftStrategyParameters.RatioEarlyUpshiftFC)) {
+					continue;
+				}
+
+				var response = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, tryNextGear);
+
+				var inAngularVelocity = ModelData.Gears[tryNextGear].Ratio * outAngularVelocity;
+				var inTorque = response.ClutchPowerRequest / inAngularVelocity;
+
+				// if next gear supplied enough power reserve: take it
+				// otherwise take
+				if (IsBelowDownShiftCurve(tryNextGear, inTorque, inAngularVelocity)) {
+					continue;
+				}
+
+				var fullLoadPower = response.EnginePowerRequest - response.DeltaFullLoad;
+				var reserve = 1 - response.EnginePowerRequest / fullLoadPower;
+
+				if (fcCurrent == null) {
+					var responseCurrent = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, currentGear);
+					fcCurrent = fcMap.GetFuelConsumption(
+						responseCurrent.EngineTorqueDemand.LimitTo(
+							fld[currentGear].DragLoadStationaryTorque(responseCurrent.EngineSpeed),
+							fld[currentGear].FullLoadStationaryTorque(responseCurrent.EngineSpeed))
+						, responseCurrent.EngineSpeed).Value;
+				}
+				var fcNext = fcMap.GetFuelConsumption(
+					response.EngineTorqueDemand.LimitTo(
+						fld[tryNextGear].DragLoadStationaryTorque(response.EngineSpeed),
+						fld[tryNextGear].FullLoadStationaryTorque(response.EngineSpeed)), response.EngineSpeed).Value;
+
+				if (reserve < ModelData.TorqueReserve ||
+					!fcNext.IsSmaller(fcCurrent * shiftStrategyParameters.RatingFactorCurrentGear) || !fcNext.IsSmaller(minFc)) {
+					continue;
+				}
+
+				minFcGear = tryNextGear;
+				minFc = fcNext.Value();
+			}
+
+			if (currentGear != minFcGear) {
+				return minFcGear;
 			}
 
 			return base.CheckEarlyUpshift(absTime, dt, outTorque, outAngularVelocity, currentGear);
@@ -108,42 +160,53 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		protected virtual uint CheckEarlyDownshift(
 			Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, uint currentGear)
 		{
-			if (ModelData.Gears[currentGear - 1].Ratio <= shiftStrategyParameters.RatioEarlyDownshiftFC) {
-				return OverdriveDownshift(absTime, dt, outTorque, outAngularVelocity, currentGear);
-			}
+			var minFcGear = currentGear;
+			var minFc = double.MaxValue;
+			KilogramPerSecond fcCurrent = null;
 
-			return currentGear;
-		}
+			for (var i = 1; i <= shiftStrategyParameters.AllowedGearRangeFC; i++) {
+				var tryNextGear = (uint)(currentGear - i);
 
-		private uint OverdriveDownshift(
-			Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, uint currentGear)
-		{
-			var tryNextGear = currentGear - 1;
-			var response = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, tryNextGear);
+				if (tryNextGear <= 1 || !(ModelData.Gears[tryNextGear].Ratio <= shiftStrategyParameters.RatioEarlyDownshiftFC)) {
+					continue;
+				}
 
-			var inAngularVelocity = ModelData.Gears[tryNextGear].Ratio * outAngularVelocity;
-			var inTorque = response.ClutchPowerRequest / inAngularVelocity;
+				var response = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, tryNextGear);
 
-			if (!IsAboveUpShiftCurve(tryNextGear, inTorque, inAngularVelocity)) {
-				var responseCurrent = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, currentGear);
-				var fcCurrent = fcMap.GetFuelConsumption(
-					responseCurrent.EngineTorqueDemand.LimitTo(
-						fld[currentGear].DragLoadStationaryTorque(responseCurrent.EngineSpeed),
-						fld[currentGear].FullLoadStationaryTorque(responseCurrent.EngineSpeed))
-					, responseCurrent.EngineSpeed);
+				var inAngularVelocity = ModelData.Gears[tryNextGear].Ratio * outAngularVelocity;
+				var inTorque = response.ClutchPowerRequest / inAngularVelocity;
+
+				if (IsAboveUpShiftCurve(tryNextGear, inTorque, inAngularVelocity)) {
+					continue;
+				}
+
+				
+				if (fcCurrent == null) {
+					var responseCurrent = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, currentGear);
+					fcCurrent = fcMap.GetFuelConsumption(
+						responseCurrent.EngineTorqueDemand.LimitTo(
+							fld[currentGear].DragLoadStationaryTorque(responseCurrent.EngineSpeed),
+							fld[currentGear].FullLoadStationaryTorque(responseCurrent.EngineSpeed))
+						, responseCurrent.EngineSpeed).Value;
+				}
 				var fcNext = fcMap.GetFuelConsumption(
 					response.EngineTorqueDemand.LimitTo(
 						fld[tryNextGear].DragLoadStationaryTorque(response.EngineSpeed),
-						fld[tryNextGear].FullLoadStationaryTorque(response.EngineSpeed)), response.EngineSpeed);
+						fld[tryNextGear].FullLoadStationaryTorque(response.EngineSpeed)), response.EngineSpeed).Value;
 
-				if (fcNext.Value.IsSmaller(fcCurrent.Value * shiftStrategyParameters.RatingFactorCurrentGear)) {
-					currentGear = tryNextGear;
+				if (!fcNext.IsSmaller(fcCurrent * shiftStrategyParameters.RatingFactorCurrentGear) ||
+					!fcNext.IsSmaller(minFc)) {
+					continue;
 				}
+
+				minFcGear = tryNextGear;
+				minFc = fcNext.Value();
 			}
 
-			return currentGear;
+			return minFcGear;
 		}
 
+
 		#endregion
 
 		protected override ResponseDryRun RequestDryRunWithGear(
diff --git a/VectoCore/VectoCoreTest/Models/Simulation/ShiftStrategyV2Test.cs b/VectoCore/VectoCoreTest/Models/Simulation/ShiftStrategyV2Test.cs
index bb3476af7e..93ab14f9d1 100644
--- a/VectoCore/VectoCoreTest/Models/Simulation/ShiftStrategyV2Test.cs
+++ b/VectoCore/VectoCoreTest/Models/Simulation/ShiftStrategyV2Test.cs
@@ -47,7 +47,9 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation
 			RunJob_DeclSingle(jobFile, i);
 		}
 
-		[TestCase(@"TestData\Integration\ShiftStrategyV2\Class5_Tractor_4x2\Class5_Tractor_ENG_TCU.vecto")]
+		[TestCase(@"TestData\Integration\ShiftStrategyV2\Class5_Tractor_4x2\Class5_Tractor_ENG_TCU.vecto"),
+		TestCase(@"TestData\Integration\ShiftStrategyV2\Class5_Tractor_4x2\Class5_Tractor_ENG_FC.vecto"),
+			TestCase(@"TestData\Integration\ShiftStrategyV2\FC-Based_AT_TUG\MB_Citaro_G_MP156_ZF_Sort.vecto", 2)]
 		public void TestShiftStrategyEngineering(string jobFile, int runIdx = 0)
 		{
 			var relativeJobPath = jobFile;
diff --git a/VectoCore/VectoCoreTest/TestData/Integration/ShiftStrategyV2/Class5_Tractor_4x2/Class5_Tractor_ENG_FC.vecto b/VectoCore/VectoCoreTest/TestData/Integration/ShiftStrategyV2/Class5_Tractor_4x2/Class5_Tractor_ENG_FC.vecto
new file mode 100644
index 0000000000..533ad1cd7d
--- /dev/null
+++ b/VectoCore/VectoCoreTest/TestData/Integration/ShiftStrategyV2/Class5_Tractor_4x2/Class5_Tractor_ENG_FC.vecto
@@ -0,0 +1,45 @@
+{
+  "Header": {
+    "CreatedBy": " ()",
+    "Date": "2016-10-13T15:52:04.0766564Z",
+    "AppVersion": "3",
+    "FileVersion": 4
+  },
+  "Body": {
+    "SavedInDeclMode": false,
+    "EngineOnlyMode": false,
+    "VehicleFile": "Class5_Tractor.vveh",
+    "EngineFile": "Engine_325kW_12.7l.veng",
+    "GearboxFile": "AMT_12.vgbx",
+    "AuxiliaryAssembly": "Classic",
+    "AuxiliaryVersion": "CLASSIC",
+    "AdvancedAuxiliaryFilePath": "",
+    "ShiftStrategy": "TUGraz.VectoCore.Models.SimulationComponent.Impl.AMTShiftStrategyOptimized",
+    "TCU" :  "ShiftParameters.vtcu", 
+    "Padd": 5000.0,
+    "VACC": "Truck.vacc",
+    "StartStop": {
+      "Enabled": false,
+      "MaxSpeed": 5.0,
+      "MinTime": 5.0,
+      "Delay": 5.0
+    },
+    "LAC": {
+      "Enabled": true,
+      "PreviewDistanceFactor": 10.0,
+      "DF_offset": 2.5,
+      "DF_scaling": 1.5,
+      "DF_targetSpeedLookup": "",
+      "Df_velocityDropLookup": ""
+    },
+    "OverSpeedEcoRoll": {
+      "Mode": "Off",
+      "MinSpeed": 50.0,
+      "OverSpeed": 5.0,
+      "UnderSpeed": 5.0
+    },
+    "Cycles": [
+      "UrbanDelivery"
+    ]
+  }
+}
\ No newline at end of file
diff --git a/VectoCore/VectoCoreTest/TestData/Integration/ShiftStrategyV2/Class5_Tractor_4x2/ShiftParameters.vtcu b/VectoCore/VectoCoreTest/TestData/Integration/ShiftStrategyV2/Class5_Tractor_4x2/ShiftParameters.vtcu
index 74bc0e2b78..4ac5fc96b4 100644
--- a/VectoCore/VectoCoreTest/TestData/Integration/ShiftStrategyV2/Class5_Tractor_4x2/ShiftParameters.vtcu
+++ b/VectoCore/VectoCoreTest/TestData/Integration/ShiftStrategyV2/Class5_Tractor_4x2/ShiftParameters.vtcu
@@ -25,6 +25,11 @@
     "Diff_curr_targ_vel": 0.1,
     "EngineSpeedHighDriveOffFactor": 1.05,
     "Rating_current_gear": 0.99,
+
+    "RatioEarlyUpshiftFC": 8,
+    "RatioEarlyDownshiftFC": 21,
+    "AllowedGearRangeFC": 1,  
+
     "AccelerationReserveLookup": "AccelerationReserveLookup.csv",
     "ShareTorque99L": "ShareTq99L.csv",
     "PredictionDurationLookup": "PredictionTimeLookup.csv",
-- 
GitLab