From 9fe62aceed748670dc4ac4c78269a9addd46b476 Mon Sep 17 00:00:00 2001
From: Markus Quaritsch <markus.quaritsch@tugraz.at>
Date: Mon, 14 Jan 2019 18:17:15 +0100
Subject: [PATCH] adding new shift strategy parameter: look-back time interval
 for smoothing demanded acceleration; computation of demanded accleration;
 allow update of shift strategy state on every request.

---
 .../InputData/EngineeringInputData.cs         |   2 +
 .../InputData/FileIO/JSON/JSONTCUData.cs      |   3 +
 .../DeclarationDataAdapter.cs                 |   2 +
 .../EngineeringDataAdapter.cs                 |   2 +
 .../Models/Declaration/DeclarationData.cs     |   2 +
 .../Simulation/Data/ModalResultField.cs       |   2 +-
 .../Data/ShiftStrategyParameters.cs           |   2 +
 .../SimulationComponent/IShiftStrategy.cs     |   1 +
 .../Impl/AMTShiftStrategyV2.cs                | 120 +++++++++++++++---
 .../Impl/BaseShiftStrategy.cs                 |   2 +
 .../Impl/DistanceBasedDrivingCycle.cs         |  15 ++-
 .../SimulationComponent/Impl/GearRating.cs    |   4 +-
 .../SimulationComponent/Impl/Gearbox.cs       |   2 +
 .../OutputData/ModalDataContainer.cs          |   1 +
 .../Models/Simulation/ShiftStrategyV2Test.cs  |  24 ++--
 .../Class5_Tractor_4x2/ShiftParameters.vtcu   |   5 +-
 16 files changed, 145 insertions(+), 44 deletions(-)

diff --git a/VectoCommon/VectoCommon/InputData/EngineeringInputData.cs b/VectoCommon/VectoCommon/InputData/EngineeringInputData.cs
index 08140c2d52..9d63b0a768 100644
--- a/VectoCommon/VectoCommon/InputData/EngineeringInputData.cs
+++ b/VectoCommon/VectoCommon/InputData/EngineeringInputData.cs
@@ -415,5 +415,7 @@ namespace TUGraz.VectoCommon.InputData
 		TableData ShareIdleLow { get; }
 		TableData ShareEngineHigh { get; }
 		string Source { get; }
+		Second DriverAccelerationLookBackInterval { get; }
+		MeterPerSquareSecond DriverAccelerationThresholdLow { get; }
 	}
 }
diff --git a/VectoCore/VectoCore/InputData/FileIO/JSON/JSONTCUData.cs b/VectoCore/VectoCore/InputData/FileIO/JSON/JSONTCUData.cs
index 4505e93334..03987cd952 100644
--- a/VectoCore/VectoCore/InputData/FileIO/JSON/JSONTCUData.cs
+++ b/VectoCore/VectoCore/InputData/FileIO/JSON/JSONTCUData.cs
@@ -163,6 +163,9 @@ namespace TUGraz.VectoCore.InputData.FileIO.JSON
 			}
 		}
 
+		public Second DriverAccelerationLookBackInterval { get {return Body.GetEx<double>("DriverAccelerationLookBackInterval").SI<Second>();} }
+		public MeterPerSquareSecond DriverAccelerationThresholdLow { get { return Body.GetEx<double>("DriverAccelerationThresholdLow").SI<MeterPerSquareSecond>(); } }
+
 		#endregion
 	}
 }
diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapter.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapter.cs
index a066dd9a52..8669878954 100644
--- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapter.cs
+++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapter.cs
@@ -564,6 +564,8 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter
 				AllowedGearRangeUp = DeclarationData.GearboxTCU.AllowedGearRangeUp,
 				AllowedGearRangeDown = DeclarationData.GearboxTCU.AllowedGearRangeDown,
 				LookBackInterval = DeclarationData.GearboxTCU.LookBackInterval,
+				DriverAccelerationLookBackInterval = DeclarationData.GearboxTCU.DriverAccelerationLookBackInterval,
+				DriverAccelerationThresholdLow = DeclarationData.GearboxTCU.DriverAccelerationThresholdLow,
 				AverageCardanPowerThresholdPropulsion = DeclarationData.GearboxTCU.AverageCardanPowerThresholdPropulsion,
 				CurrentCardanPowerThresholdPropulsion = DeclarationData.GearboxTCU.CurrentCardanPowerThresholdPropulsion,
 				TargetSpeedDeviationFactor = DeclarationData.GearboxTCU.TargetSpeedDeviationFactor,
diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/EngineeringDataAdapter.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/EngineeringDataAdapter.cs
index 6606e6f527..9bb39d77b7 100644
--- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/EngineeringDataAdapter.cs
+++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/EngineeringDataAdapter.cs
@@ -417,6 +417,8 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter
 				AllowedGearRangeUp = gsInputData.AllowedGearRangeUp,
 				AllowedGearRangeDown = gsInputData.AllowedGearRangeDown,
 				LookBackInterval = gsInputData.LookBackInterval ?? DeclarationData.GearboxTCU.LookBackInterval,
+				DriverAccelerationLookBackInterval = gsInputData.DriverAccelerationLookBackInterval ?? DeclarationData.GearboxTCU.DriverAccelerationLookBackInterval,
+				DriverAccelerationThresholdLow = gsInputData.DriverAccelerationThresholdLow ?? DeclarationData.GearboxTCU.DriverAccelerationThresholdLow,
 				AverageCardanPowerThresholdPropulsion = gsInputData.AvgCardanPowerThresholdPropulsion ??
 														DeclarationData.GearboxTCU.AverageCardanPowerThresholdPropulsion,
 				CurrentCardanPowerThresholdPropulsion = gsInputData.CurrCardanPowerThresholdPropulsion ??
diff --git a/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs b/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs
index 5a8cc3ec95..979ca7980e 100644
--- a/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs
+++ b/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs
@@ -184,6 +184,7 @@ namespace TUGraz.VectoCore.Models.Declaration
 			public static readonly Watt CurrentCardanPowerThresholdPropulsion = 5000.SI<Watt>();
 			public static readonly Watt AverageCardanPowerThresholdPropulsion = 1000.SI<Watt>();
 			public static readonly Second LookBackInterval = 4.SI<Second>();
+			public static readonly Second DriverAccelerationLookBackInterval = 10.SI<Second>();
 			public const double EngineSpeedHighDriveOffFactor = 1.05;
 			public const double DnT99L_highMin1 = 0.4;
 			public const double DnT99L_highMin2 = 0.5;
@@ -191,6 +192,7 @@ namespace TUGraz.VectoCore.Models.Declaration
 			public const int AllowedGearRangeDown = 3;
 			public const double TargetSpeedDeviationFactor = 0.1;
 			public const double RatingFactorCurrentGear = 0.99;
+			public static readonly MeterPerSquareSecond DriverAccelerationThresholdLow = 0.1.SI<MeterPerSquareSecond>();
 		}
 
 		public static class Gearbox
diff --git a/VectoCore/VectoCore/Models/Simulation/Data/ModalResultField.cs b/VectoCore/VectoCore/Models/Simulation/Data/ModalResultField.cs
index a02b090f34..093202a38c 100644
--- a/VectoCore/VectoCore/Models/Simulation/Data/ModalResultField.cs
+++ b/VectoCore/VectoCore/Models/Simulation/Data/ModalResultField.cs
@@ -296,7 +296,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Data
 		/// <summary>
 		///     [m]	Altitude
 		/// </summary>
-		[ModalResultField(typeof(SI))] altitude,
+		[ModalResultField(typeof(SI), "altitude [m]")] altitude,
 
 		[ModalResultField(typeof(SI), name: "ds [m]")] simulationDistance,
 
diff --git a/VectoCore/VectoCore/Models/Simulation/Data/ShiftStrategyParameters.cs b/VectoCore/VectoCore/Models/Simulation/Data/ShiftStrategyParameters.cs
index 2645babc4b..d79c2f37ff 100644
--- a/VectoCore/VectoCore/Models/Simulation/Data/ShiftStrategyParameters.cs
+++ b/VectoCore/VectoCore/Models/Simulation/Data/ShiftStrategyParameters.cs
@@ -41,9 +41,11 @@ namespace TUGraz.VectoCore.Models.Simulation.Data {
 		public int AllowedGearRangeDown { get; set; }
 		public int AllowedGearRangeUp { get; set; }
 		public Second LookBackInterval { get; set; }
+		public Second DriverAccelerationLookBackInterval { get; set; }
 		public Watt AverageCardanPowerThresholdPropulsion { get; set; }
 		public Watt CurrentCardanPowerThresholdPropulsion { get; set; }
 		public double TargetSpeedDeviationFactor { get; set; }
 		public double RatingFactorCurrentGear { get; set; }
+		public MeterPerSquareSecond DriverAccelerationThresholdLow { get; set; }
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/IShiftStrategy.cs b/VectoCore/VectoCore/Models/SimulationComponent/IShiftStrategy.cs
index 54d4424cb0..5064cb11fd 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/IShiftStrategy.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/IShiftStrategy.cs
@@ -91,6 +91,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent
 		IGearbox Gearbox { get; set; }
 
         GearInfo NextGear { get; }
+		void Request(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity);
 	}
 
     public class GearInfo
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/AMTShiftStrategyV2.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/AMTShiftStrategyV2.cs
index 1cb3ca26a7..807d98841b 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/AMTShiftStrategyV2.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/AMTShiftStrategyV2.cs
@@ -28,6 +28,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		protected Dictionary<uint, PerSecond> EngineSpeedAtDriveOff;
 		protected SimplePowertrainContainer TestContainer;
 		protected Dictionary<Second, HistoryEntry> HistoryBuffer = new Dictionary<Second, HistoryEntry>();
+		protected Dictionary<Second, AccelerationEntry> AccelerationBuffer = new Dictionary<Second, AccelerationEntry>();
 		protected AverageAccelerationTorqueLookup AverageAccelerationTorqueLookup;
 		protected MaxCardanTorqueLookup MaxCardanTorqueLookup;
 
@@ -35,6 +36,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		private Dictionary<uint, GearRating> GearRatings = new Dictionary<uint, GearRating>();
 		private MeterPerSquareSecond accRsv = 0.SI<MeterPerSquareSecond>();
 		private MeterPerSecond demandedSpeed = 0.SI<MeterPerSecond>();
+		private MeterPerSquareSecond driverAccelerationAvg;
 
 		public struct HistoryEntry
 		{
@@ -43,6 +45,18 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			public Watt AvgCardanPower;
 		}
 
+		[DebuggerDisplay("dt: {dt}, acc: {Acceleration}")]
+		public struct AccelerationEntry
+		{
+			public Second dt;
+			public MeterPerSquareSecond Acceleration;
+
+			public override string ToString()
+			{
+				return string.Format("dt: {0} acc: {1}", dt, Acceleration);
+			}
+		}
+
 		public AMTShiftStrategyV2(VectoRunData data, IVehicleContainer dataBus) : base(data.GearboxData, dataBus)
 		{
 			PowertrainConfig = data;
@@ -89,9 +103,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 
 		#region Overrides of BaseShiftStrategy
 
-		public override bool ShiftRequired(
-			Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, NewtonMeter inTorque,
-			PerSecond inAngularVelocity, uint gear, Second lastShiftTime)
+		public override void Request(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity)
 		{
 			// update own history
 			var velocity = DataBus.VehicleSpeed + DataBus.DriverAcceleration * dt / 2.0;
@@ -100,6 +112,22 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 
 			UpdateHistoryBuffer(absTime, dt, currentCardanPower, velocity);
 
+			var currentVelocity = DataBus.VehicleSpeed;
+			accRsv = CalcAccelerationReserve(currentVelocity, absTime + dt);
+
+			driverAccelerationAvg = GetAverageAcceleration(absTime + dt);
+		}
+
+
+		public override bool ShiftRequired(
+			Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, NewtonMeter inTorque,
+			PerSecond inAngularVelocity, uint gear, Second lastShiftTime)
+		{
+			
+			var cardanDemand = DataBus.CurrentAxleDemand;
+			var currentCardanPower = cardanDemand.Item1 * cardanDemand.Item2;
+
+
 			// no shift when vehicle stands
 			if (DataBus.VehicleStopped) {
 				return false;
@@ -164,7 +192,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			var lookAheadDistance =
 				DataBus.VehicleSpeed * ModelData.TractionInterruption; //ShiftStrategyParameters.GearResidenceTime;
 			var roadGradient = DataBus.CycleLookAhead(lookAheadDistance).RoadGradient;
-			var minRating = new GearRating(GearRatingCase.E, double.MaxValue, 0.RPMtoRad());
+			var minRating = new GearRating(GearRatingCase.Z, double.MaxValue, 0.RPMtoRad());
 			var selectedGear = gear;
 			var debugData = new DebugData();
 
@@ -173,7 +201,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			var estimatedVelocityPostShift = VelocityDropData.Interpolate(currentVelocity, gradient);
 			var predictionVelocity = CalcPredictionVelocity(currentVelocity, estimatedVelocityPostShift);
 
-			accRsv = CalcAccelerationReserve(currentVelocity, absTime + dt);
+			
+			if (driverAccelerationAvg <= ShiftStrategyParameters.DriverAccelerationThresholdLow) {
+				driverAccelerationAvg = 0.SI<MeterPerSquareSecond>();
+			}
 
 			GearRatings.Clear();
 			for (var i = Math.Max(1, gear - ShiftStrategyParameters.AllowedGearRangeDown);
@@ -197,7 +228,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 					continue;
 				}
 
-				var rating = RatingGear(false, nextGear, gear, gradient, predictionVelocity, estimatedVelocityPostShift, accRsv);
+				var rating = RatingGear(false, nextGear, gear, gradient, predictionVelocity, estimatedVelocityPostShift, accRsv, driverAccelerationAvg);
 				if (nextGear == gear) {
 					if (rating.RatingCase == GearRatingCase.A) {
 						rating = new GearRating(
@@ -225,6 +256,27 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			return _nextGear != gear;
 		}
 
+		private MeterPerSquareSecond GetAverageAcceleration(Second absTime)
+		{
+			if (!AccelerationBuffer.Any()) {
+				return 0.SI<MeterPerSquareSecond>();
+			}
+
+			var sumTime = 0.SI<Second>();
+			var sumAcc = 0.SI<MeterPerSecond>();
+			var start = absTime - ShiftStrategyParameters.DriverAccelerationLookBackInterval;
+
+			foreach (var entry in AccelerationBuffer) {
+				var time = VectoMath.Max(VectoMath.Min(entry.Key - start, 0.SI<Second>()) + entry.Value.dt, 0.SI<Second>());
+				var acc = entry.Value.Acceleration * time;
+				sumTime += time;
+				sumAcc += acc;
+			}
+			var avgAcc = sumAcc / VectoMath.Max(sumTime, 10.SI<Second>());
+
+			return avgAcc > 0.1.SI<MeterPerSquareSecond>() ? avgAcc : 0.SI<MeterPerSquareSecond>();
+		}
+
 		private bool UpshiftAllowed(Second absTime)
 		{
 			return (absTime - _gearbox.LastDownshift).IsGreaterOrEqual(_gearbox.ModelData.UpshiftAfterDownshiftDelay);
@@ -237,7 +289,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 
 		private GearRating RatingGear(
 			bool driveOff, uint gear, uint currentGear, Radian gradient, MeterPerSecond predictionVelocity,
-			MeterPerSecond velocityAfterGearshift, MeterPerSquareSecond accRsv)
+			MeterPerSecond velocityAfterGearshift, MeterPerSquareSecond accRsv, MeterPerSquareSecond driverAccelerationAvg)
 		{
 			TestContainer.GearboxCtl.Gear = gear;
 			TestContainer.VehiclePort.Initialize(predictionVelocity, gradient);
@@ -248,7 +300,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 				0.SI<Second>(), Constants.SimulationSettings.TargetTimeInterval,
 				0.SI<MeterPerSquareSecond>(), gradient, true);
 			var respDriverDemand = (ResponseDryRun)TestContainer.VehiclePort.Request(
-				0.SI<Second>(), Constants.SimulationSettings.TargetTimeInterval, DataBus.DriverAcceleration, gradient,
+				0.SI<Second>(), Constants.SimulationSettings.TargetTimeInterval, driverAccelerationAvg, gradient,
 				true);
 
 			if (respAccRsv.EngineSpeed < PowertrainConfig.EngineData.IdleSpeed ||
@@ -261,24 +313,23 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			var engineSpeedHighThreshold = GetEngineSpeedLimitHigh(
 				driveOff, gear, respAccRsv.EngineSpeed, respConstVel.CardanTorque);
 			if (respAccRsv.EngineSpeed < engineSpeedLowThreshold) {
-				return new GearRating(
-					GearRatingCase.D, (engineSpeedLowThreshold - respAccRsv.EngineSpeed).Value(), engineSpeedHighThreshold);
+				return new GearRating(GearRatingCase.D, 
+					(engineSpeedLowThreshold - respAccRsv.EngineSpeed).AsRPM, engineSpeedHighThreshold);
 			}
 
 			if (respAccRsv.EngineSpeed > engineSpeedHighThreshold) {
-				return new GearRating(
-					GearRatingCase.D, (respAccRsv.EngineSpeed - engineSpeedHighThreshold).Value(), engineSpeedHighThreshold);
+				return new GearRating(GearRatingCase.D, 
+					(respAccRsv.EngineSpeed - engineSpeedHighThreshold).AsRPM, engineSpeedHighThreshold);
 			}
 
 			if (respAccRsv.EngineTorqueDemandTotal <= respAccRsv.EngineDynamicFullLoadTorque) {
 				var fc = PowertrainConfig.EngineData.ConsumptionMap.GetFuelConsumption(
-					VectoMath.Max(
-						respAccRsv.EngineTorqueDemandTotal,
-						PowertrainConfig.EngineData.FullLoadCurves[0].DragLoadStationaryTorque(respAccRsv.EngineSpeed)),
+					respDriverDemand.EngineTorqueDemandTotal.LimitTo(
+						PowertrainConfig.EngineData.FullLoadCurves[0].DragLoadStationaryTorque(respAccRsv.EngineSpeed), 
+						PowertrainConfig.EngineData.FullLoadCurves[0].FullLoadStationaryTorque(respAccRsv.EngineSpeed)),
 					respAccRsv.EngineSpeed);
-				retVal = new GearRating(
-					GearRatingCase.A,
-					(fc.Value.ConvertToGrammPerHour().Value / VectoMath.Max(respAccRsv.AxlegearPowerRequest, 1.SI<Watt>())).Value(),
+				retVal = new GearRating(GearRatingCase.A,
+					(fc.Value.ConvertToGrammPerHour().Value / VectoMath.Max(respAccRsv.AxlegearPowerRequest, 1.SI<Watt>())).Value() * 1e3,
 					engineSpeedHighThreshold);
 			} else {
 				retVal = new GearRating(
@@ -416,10 +467,36 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 				AvgCardanPower = currentCardanPower,
 				AvgSpeed = velocity,
 			};
-			var oldEntries = HistoryBuffer.Keys.Where(x => x < absTime - ShiftStrategyParameters.LookBackInterval).ToArray();
+			var oldEntries = HistoryBuffer.Keys.Where(x => x < absTime + dt - ShiftStrategyParameters.LookBackInterval).ToArray();
 			foreach (var entry in oldEntries) {
 				HistoryBuffer.Remove(entry);
 			}
+
+			var aDemanded = 0.SI<MeterPerSquareSecond>();
+			var aLimit = PowertrainConfig.DriverData.AccelerationCurve.Lookup(DataBus.VehicleSpeed);
+			if (DataBus.DriverBehavior == DrivingBehavior.Braking) {
+				if (DataBus.DrivingAction == DrivingAction.Brake) {
+					aDemanded = aLimit.Deceleration;
+				}
+			} else {
+				var lastTargetspeedChange = DataBus.LastTargetspeedChange;
+				var vDemanded = ComputeDemandedSpeed(lastTargetspeedChange, absTime);
+				aDemanded = (vDemanded - DataBus.VehicleSpeed) / dt;
+				
+				aDemanded = aDemanded.LimitTo(aLimit.Deceleration, aLimit.Acceleration);
+			}
+			AccelerationBuffer[absTime] = new AccelerationEntry() {
+				dt = dt,
+				Acceleration = VectoMath.Max(aDemanded, 0.SI<MeterPerSquareSecond>())
+			};
+
+			var outdated = AccelerationBuffer
+				.Where(x => x.Key + x.Value.dt < absTime - ShiftStrategyParameters.DriverAccelerationLookBackInterval)
+				.Select(x => x.Key).ToArray();
+			
+			foreach (var entry in outdated) {
+				AccelerationBuffer.Remove(entry);
+			}
 		}
 
 		public override uint InitGear(Second absTime, Second dt, NewtonMeter torque, PerSecond outAngularVelocity)
@@ -460,7 +537,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 				var engineSpeedAboveMin = engineSpeed > engineSpeedLimitLow;
 				var engineSpeedBelowN95h = engineSpeed < PowertrainConfig.EngineData.FullLoadCurves[0].N95hSpeed;
 				if (gradientBelowMaxGrad && engineSpeedAboveMin && engineSpeedBelowN95h) {
-					var rating = RatingGear(true, i, 0, roadGradient, predictionVelocity, estimatedVelocityPostShift, accRsv);
+					var rating = RatingGear(true, i, 0, roadGradient, predictionVelocity, estimatedVelocityPostShift, accRsv, accRsv);
 					GearRatings[i] = rating;
 					if (rating < minRating) {
 						minRating = rating;
@@ -520,7 +597,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 
 			var engineAcceleration = (acceleration / ratio).Cast<PerSquareSecond>();
 			var deltaEngineSpeed = engineSpeedHighThreshold - engineSpeed;
-			if (engineAcceleration > 0 && deltaEngineSpeed > 0) {
+			if (engineAcceleration.IsGreater(0) && deltaEngineSpeed > 0) {
 				return (deltaEngineSpeed / engineAcceleration).Cast<Second>();
 			}
 
@@ -581,6 +658,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 
 			container.SetDataValue("acc_rsv", accRsv?.Value() ?? 0);
 			container.SetDataValue("v_dem", demandedSpeed?.AsKmph ?? 0);
+			container.SetDataValue("acc_driver_avg", driverAccelerationAvg?.Value() ?? 0);
 			GearRatings.Clear();
 			accRsv = null;
 		}
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/BaseShiftStrategy.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/BaseShiftStrategy.cs
index 63411e4b99..d00f404597 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/BaseShiftStrategy.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/BaseShiftStrategy.cs
@@ -58,6 +58,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		public abstract void Disengage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outEngineSpeed);
 		public abstract IGearbox Gearbox { get; set; }
 		public abstract GearInfo NextGear { get; }
+		public virtual void Request(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity)
+		{ }
 
 		protected MeterPerSquareSecond EstimateAccelerationForGear(uint gear, PerSecond gbxAngularVelocityOut)
 		{
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs
index 031dc95f00..354d027ffb 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs
@@ -82,6 +82,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 				WaitTime = 0.SI<Second>(),
 				Distance = first.Distance,
 				Altitude = first.Altitude,
+				VehicleTargetSpeed = Data.Entries.First().VehicleTargetSpeed
 			};
 			CurrentState = PreviousState.Clone();
 		}
@@ -481,20 +482,20 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 				myIterator.MoveNext();
 			}
 
-			return InterpolateCycleEntry(absDistance, myIterator.RightSample);
+			return InterpolateCycleEntry(absDistance, myIterator);
 		}
 
 		private DrivingCycleData.DrivingCycleEntry InterpolateCycleEntry(Meter absDistance,
-			DrivingCycleData.DrivingCycleEntry lookahead)
+			DrivingCycleEnumerator lookahead)
 		{
-			var retVal = new DrivingCycleData.DrivingCycleEntry(lookahead) {
+			var retVal = new DrivingCycleData.DrivingCycleEntry(lookahead.RightSample) {
 				Distance = absDistance,
-				Altitude = VectoMath.Interpolate(CurrentState.Distance, lookahead.Distance, CurrentState.Altitude,
-					lookahead.Altitude, absDistance)
+				Altitude = VectoMath.Interpolate(lookahead.LeftSample.Distance, lookahead.RightSample.Distance, lookahead.LeftSample.Altitude,
+					lookahead.RightSample.Altitude, absDistance)
 			};
 
-			retVal.RoadGradient =
-				((retVal.Altitude - CurrentState.Altitude) / (absDistance - CurrentState.Distance)).Value().SI<Radian>();
+			//retVal.RoadGradient =
+			//	((retVal.Altitude - CurrentState.Altitude) / (absDistance - CurrentState.Distance)).Value().SI<Radian>();
 
 			return retVal;
 		}
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/GearRating.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/GearRating.cs
index f121a03358..eba14be602 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/GearRating.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/GearRating.cs
@@ -15,7 +15,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl {
 
 	internal struct GearRating
 	{
-		private const double CaseSeparationInterval = 1e6;
+		private const double CaseSeparationInterval = 1e5;
 
 		public GearRating(GearRatingCase ratingCase, double rating, PerSecond maxEngineSpeed)
 		{
@@ -31,7 +31,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl {
 
 		public double NumericValue
 		{
-			get { return ((int)RatingCase - 1) * CaseSeparationInterval + (Rating * 100).LimitTo(0, CaseSeparationInterval-10); }
+			get { return ((int)RatingCase - 1) * CaseSeparationInterval + Rating.LimitTo(0, CaseSeparationInterval-1); }
 		}
 
 		public static bool operator <(GearRating first, GearRating second)
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs
index 60467dbcf4..6bfdecae50 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs
@@ -175,6 +175,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		{
 			IterationStatistics.Increment(this, "Requests");
 
+			_strategy?.Request(absTime, dt, outTorque, outAngularVelocity);
+
 			Log.Debug("Gearbox Power Request: torque: {0}, angularVelocity: {1}", outTorque, outAngularVelocity);
 			if (DataBus.VehicleStopped) {
 				EngageTime = absTime;
diff --git a/VectoCore/VectoCore/OutputData/ModalDataContainer.cs b/VectoCore/VectoCore/OutputData/ModalDataContainer.cs
index 4929ac8580..ed46223ec9 100644
--- a/VectoCore/VectoCore/OutputData/ModalDataContainer.cs
+++ b/VectoCore/VectoCore/OutputData/ModalDataContainer.cs
@@ -250,6 +250,7 @@ namespace TUGraz.VectoCore.OutputData
 			// TODO: 2018-11-20: Disable additional columns after testing gearshifting!
 //#if TRACE
 			strCols = strCols.Concat(_additionalColumns);
+			dataColumns.Add(ModalResultField.altitude);
 //#endif
 			if (WriteModalResults) {
 				var filteredData = Data;
diff --git a/VectoCore/VectoCoreTest/Models/Simulation/ShiftStrategyV2Test.cs b/VectoCore/VectoCoreTest/Models/Simulation/ShiftStrategyV2Test.cs
index 2e70280de3..acf5cabd50 100644
--- a/VectoCore/VectoCoreTest/Models/Simulation/ShiftStrategyV2Test.cs
+++ b/VectoCore/VectoCoreTest/Models/Simulation/ShiftStrategyV2Test.cs
@@ -193,7 +193,7 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation
 			//TestCase("Tractor_6x2_vehicle-class-10_EURO6_2018.xml", 2, TestName = "AMT ShiftV2 Group10 LH EMS Los"),
 			//TestCase("Tractor_6x2_vehicle-class-10_EURO6_2018.xml", 3, TestName = "AMT ShiftV2 Group10 LH EMS Ref"),
 			//TestCase("Tractor_6x2_vehicle-class-10_EURO6_2018.xml", 4, TestName = "AMT ShiftV2 Group10 RD Low"),
-			//TestCase("Tractor_6x2_vehicle-class-10_EURO6_2018.xml", 5, TestName = "AMT ShiftV2 Group10 RD Ref"),
+			TestCase("Tractor_6x2_vehicle-class-10_EURO6_2018.xml", 5, TestName = "AMT ShiftV2 Group10 RD Ref"),
 			//TestCase("Tractor_6x2_vehicle-class-10_EURO6_2018.xml", 6, TestName = "AMT ShiftV2 Group10 RD EMS Low"),
 			//TestCase("Tractor_6x2_vehicle-class-10_EURO6_2018.xml", 7, TestName = "AMT ShiftV2 Group10 RD EMS Ref"),
 			]
@@ -235,17 +235,17 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation
 			}
 		}
 
-		[//TestCase("Tractor_6x4_vehicle-class-12_EURO6_2018.xml", null, TestName = "AMT ShiftV2 Group 11 ALL"),
-			TestCase("Tractor_6x4_vehicle-class-12_EURO6_2018.xml", 0, TestName = "AMT ShiftV2 Group11 LH Low"),
-			TestCase("Tractor_6x4_vehicle-class-12_EURO6_2018.xml", 1, TestName = "AMT ShiftV2 Group11 LH Ref"),
-			TestCase("Tractor_6x4_vehicle-class-12_EURO6_2018.xml", 2, TestName = "AMT ShiftV2 Group11 LH EMS Low"),
-			TestCase("Tractor_6x4_vehicle-class-12_EURO6_2018.xml", 3, TestName = "AMT ShiftV2 Group11 LH EMS Ref"),
-			TestCase("Tractor_6x4_vehicle-class-12_EURO6_2018.xml", 4, TestName = "AMT ShiftV2 Group11 RD Low"),
-			TestCase("Tractor_6x4_vehicle-class-12_EURO6_2018.xml", 5, TestName = "AMT ShiftV2 Group11 RD Ref"),
-			TestCase("Tractor_6x4_vehicle-class-12_EURO6_2018.xml", 6, TestName = "AMT ShiftV2 Group11 RD EMS Low"),
-			TestCase("Tractor_6x4_vehicle-class-12_EURO6_2018.xml", 7, TestName = "AMT ShiftV2 Group11 RD EMS Ref"),
-			TestCase("Tractor_6x4_vehicle-class-12_EURO6_2018.xml", 8, TestName = "AMT ShiftV2 Group11 CO Low"),
-			TestCase("Tractor_6x4_vehicle-class-12_EURO6_2018.xml", 9, TestName = "AMT ShiftV2 Group11 CO Ref"),
+		[//TestCase("Tractor_6x4_vehicle-class-12_EURO6_2018.xml", null, TestName = "AMT ShiftV2 Group 12 ALL"),
+			TestCase("Tractor_6x4_vehicle-class-12_EURO6_2018.xml", 0, TestName = "AMT ShiftV2 Group12 LH Low"),
+			TestCase("Tractor_6x4_vehicle-class-12_EURO6_2018.xml", 1, TestName = "AMT ShiftV2 Group12 LH Ref"),
+			TestCase("Tractor_6x4_vehicle-class-12_EURO6_2018.xml", 2, TestName = "AMT ShiftV2 Group12 LH EMS Low"),
+			TestCase("Tractor_6x4_vehicle-class-12_EURO6_2018.xml", 3, TestName = "AMT ShiftV2 Group12 LH EMS Ref"),
+			TestCase("Tractor_6x4_vehicle-class-12_EURO6_2018.xml", 4, TestName = "AMT ShiftV2 Group12 RD Low"),
+			TestCase("Tractor_6x4_vehicle-class-12_EURO6_2018.xml", 5, TestName = "AMT ShiftV2 Group12 RD Ref"),
+			TestCase("Tractor_6x4_vehicle-class-12_EURO6_2018.xml", 6, TestName = "AMT ShiftV2 Group12 RD EMS Low"),
+			TestCase("Tractor_6x4_vehicle-class-12_EURO6_2018.xml", 7, TestName = "AMT ShiftV2 Group12 RD EMS Ref"),
+			TestCase("Tractor_6x4_vehicle-class-12_EURO6_2018.xml", 8, TestName = "AMT ShiftV2 Group12 CO Low"),
+			TestCase("Tractor_6x4_vehicle-class-12_EURO6_2018.xml", 9, TestName = "AMT ShiftV2 Group12 CO Ref"),
 		]
 		public void RunDeclarationTestNewShiftStrategy_Group12(string filename, int? idx)
 		{
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 0e81a64e5e..967bf2997c 100644
--- a/VectoCore/VectoCoreTest/TestData/Integration/ShiftStrategyV2/Class5_Tractor_4x2/ShiftParameters.vtcu
+++ b/VectoCore/VectoCoreTest/TestData/Integration/ShiftStrategyV2/Class5_Tractor_4x2/ShiftParameters.vtcu
@@ -14,6 +14,8 @@
     "GearRangeUp": 3,
     "GearRangeDown": 3,
     "LookBackDriver": 4,
+    "DriverAccelerationLookBackInterval":  10, 
+    "DriverAccelerationThresholdLow":  0.1,
     "P_card_avg_threshold": 5000,
     "P_card_curr_threshold": 1000,
     "Diff_curr_targ_vel": 0.1,
@@ -23,6 +25,7 @@
     "ShareTorque99L": "ShareTq99L.csv",
     "PredictionDurationLookup": "PredictionTimeLookup.csv",
     "ShareIdleLow": "ShareIdleLow.csv",
-     "ShareEngineHigh": "ShareEngineSpeedHigh.csv" 
+    "ShareEngineHigh": "ShareEngineSpeedHigh.csv"
+   
   }
 }
\ No newline at end of file
-- 
GitLab