From e875ea4c2d06759f5b52599a1ee3420946db5f36 Mon Sep 17 00:00:00 2001
From: Markus Quaritsch <markus.quaritsch@tugraz.at>
Date: Thu, 28 Oct 2021 12:35:04 +0200
Subject: [PATCH] torque converter: in case an operating point has been set in
 the driver model, ignore acceleration limits reset gearbox disengaged state
 if set by driver model after the simulation interval

---
 .../Models/SimulationComponent/Impl/Driver.cs | 143 ++++++++++--------
 1 file changed, 80 insertions(+), 63 deletions(-)

diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Driver.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Driver.cs
index 95d8a6a35f..51e4055770 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Driver.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Driver.cs
@@ -56,6 +56,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		Accelerate = 6,
 		Brake = -5,
 	}
+
 	public class Driver :
 		StatefulProviderComponent<Driver.DriverState, IDrivingCycleOutPort, IDriverDemandInPort, IDriverDemandOutPort>,
 		IDriver, IDrivingCycleOutPort, IDriverDemandInPort, IDriverActions, IDriverInfo
@@ -64,6 +65,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 
 		protected readonly IDriverStrategy DriverStrategy;
 		protected readonly bool smartBusAux;
+		private bool? _previousGearboxDisengaged = null;
 
 		public DrivingAction DrivingAction { get; protected internal set; }
 
@@ -429,6 +431,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 					requestedOperatingPoint.Acceleration, initialResponse, coastingOrRoll: true);
 			}
 
+			var tcOperatingPointSet = false;
 			if (searchedOperatingPoint == null && DataBus.GearboxInfo.GearboxType.AutomaticTransmission()) {
 				// we end up here if no valid operating point for the engine and torque converter can be found.
 				// a likely reason is that the torque converter opereating point 'jumps' between two different operating points
@@ -436,6 +439,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 				// solution where a torque converter operating point is searched by forward calculation first and then the remaining
 				// powertrain is adjusted to this operating point.
 				searchedOperatingPoint = SetTCOperatingPointATGbxCoastOrRoll(absTime, gradient, requestedOperatingPoint, initialResponse as ResponseDryRun);
+				tcOperatingPointSet = true;
 			}
 
 			if (searchedOperatingPoint == null) {
@@ -474,8 +478,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 				searchedOperatingPoint.SimulationInterval,
 				searchedOperatingPoint.Acceleration, rollAction ? "ROLL" : "COAST");
 
+			var applyLimit = rollAction || tcOperatingPointSet;
+
 			var limitedOperatingPoint = LimitAccelerationByDriverModel(searchedOperatingPoint,
-				rollAction ? LimitationMode.NoLimitation : LimitationMode.LimitDecelerationDriver);
+				applyLimit ? LimitationMode.NoLimitation : LimitationMode.LimitDecelerationDriver);
 
 			// compute speed at the end of the simulation interval. if it exceeds the limit -> return
 			var v2 = DataBus.VehicleInfo.VehicleSpeed +
@@ -911,7 +917,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			var tcOp = DataBus.TorqueConverterInfo.CalculateOperatingPoint(DataBus.EngineInfo.EngineIdleSpeed * 1.01, response.Gearbox.InputSpeed);
 
 			if (!tcOp.Item2.IsBetween(dragTorque - inertiaTq - auxTqDemand, maxTorque - inertiaTq - auxTqDemand)) {
-
+				_previousGearboxDisengaged = DataBus.GearboxInfo.DisengageGearbox;
 				DataBus.GearboxCtl.DisengageGearbox = true;
 				operatingPoint = SearchBrakingPower(
 					absTime, operatingPoint.SimulationDistance, gradient,
@@ -1194,7 +1200,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 						(response, cnt) => {
 							var r = (ResponseDryRun)response;
 							if (DataBus.GearboxInfo.GearboxType.AutomaticTransmission() &&
-								r.DeltaDragLoad.Value().IsSmallerOrEqual(-double.MaxValue / 20)) {
+								r.DeltaDragLoad.Value().IsSmallerOrEqual(-double.MaxValue / 20) && coastingOrRoll && !actionRoll ) {
 								nanCount++;
 							}
 							if (nanCount > 10) {
@@ -1202,7 +1208,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 							}
 							return r != null && !actionRoll && !allowDistanceDecrease && !ds.IsEqual(r.Driver.OperatingPoint.SimulationDistance);
 						});
-				return ComputeTimeInterval(retVal.Acceleration, retVal.SimulationDistance);
+					return ComputeTimeInterval(retVal.Acceleration, retVal.SimulationDistance);
 			} catch (VectoException ve) {
 				switch (ve) {
 					case VectoSearchFailedException _:
@@ -1211,69 +1217,76 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 						// search aborted, try to go ahead with the last acceleration
 						if (!searchEngineSpeed && !actionRoll && !coastingOrRoll) {
 							var nanCount1 = 0;
-							retVal.Acceleration = SearchAlgorithm.Search(acceleration, delta,
-								Constants.SimulationSettings.OperatingPointInitialSearchIntervalAccelerating,
-								getYValue: response => {
-									var r = (ResponseDryRun)response;
-
-									return (r.DeltaFullLoad);
-								},
-								evaluateFunction:
-								acc => {
-									// calculate new time interval only when vehiclespeed and acceleration are != 0
-									// else: use same timeinterval as before.
-									var vehicleDrivesAndAccelerates =
+							try {
+								retVal.Acceleration = SearchAlgorithm.Search(acceleration, delta,
+									Constants.SimulationSettings.OperatingPointInitialSearchIntervalAccelerating,
+									getYValue: response => {
+										var r = (ResponseDryRun)response;
+
+										return (r.DeltaFullLoad);
+									},
+									evaluateFunction:
+									acc => {
+										// calculate new time interval only when vehiclespeed and acceleration are != 0
+										// else: use same timeinterval as before.
+										var vehicleDrivesAndAccelerates =
 											!(acc.IsEqual(0) && DataBus.VehicleInfo.VehicleSpeed.IsEqual(0));
-									if (vehicleDrivesAndAccelerates) {
-										var tmp = ComputeTimeInterval(acc, ds);
-										if (tmp.SimulationInterval.IsEqual(0.SI<Second>(), 1e-9.SI<Second>())) {
-											throw new VectoSearchAbortedException(
-												"next TimeInterval is 0. a: {0}, v: {1}, dt: {2}", acc,
-												DataBus.VehicleInfo.VehicleSpeed, tmp.SimulationInterval);
+										if (vehicleDrivesAndAccelerates) {
+											var tmp = ComputeTimeInterval(acc, ds);
+											if (tmp.SimulationInterval.IsEqual(0.SI<Second>(), 1e-9.SI<Second>())) {
+												throw new VectoSearchAbortedException(
+													"next TimeInterval is 0. a: {0}, v: {1}, dt: {2}", acc,
+													DataBus.VehicleInfo.VehicleSpeed, tmp.SimulationInterval);
+											}
+
+											retVal.Acceleration = tmp.Acceleration;
+											retVal.SimulationInterval = tmp.SimulationInterval;
+											retVal.SimulationDistance = tmp.SimulationDistance;
+
+
+										} else {
+											retVal.Acceleration = acc;
+											retVal.SimulationDistance = 0.SI<Meter>();
+										}
+
+										IterationStatistics.Increment(this, "SearchOperatingPoint");
+										DriverAcceleration = acc;
+										var response = NextComponent.Request(absTime, retVal.SimulationInterval, acc,
+											gradient,
+											true);
+										response.Driver.OperatingPoint = retVal;
+										return response;
+
+									},
+									criterion: response => {
+										var r = (ResponseDryRun)response;
+
+										delta = (r.DeltaFullLoad);
+										return Math.Max(delta.Value(), 0);
+									},
+									abortCriterion:
+									(response, cnt) => {
+										var r = (ResponseDryRun)response;
+										if (DataBus.GearboxInfo.GearboxType.AutomaticTransmission() &&
+											r.DeltaDragLoad.Value().IsSmallerOrEqual(-double.MaxValue / 20) && coastingOrRoll && !actionRoll) {
+											nanCount1++;
 										}
 
-										retVal.Acceleration = tmp.Acceleration;
-										retVal.SimulationInterval = tmp.SimulationInterval;
-										retVal.SimulationDistance = tmp.SimulationDistance;
-
-
-									} else {
-										retVal.Acceleration = acc;
-										retVal.SimulationDistance = 0.SI<Meter>();
-									}
-
-									IterationStatistics.Increment(this, "SearchOperatingPoint");
-									DriverAcceleration = acc;
-									var response = NextComponent.Request(absTime, retVal.SimulationInterval, acc, gradient,
-										true);
-									response.Driver.OperatingPoint = retVal;
-									return response;
-
-								},
-								criterion: response => {
-									var r = (ResponseDryRun)response;
-
-									delta = (r.DeltaFullLoad);
-									return Math.Max(delta.Value(), 0);
-								},
-								abortCriterion:
-								(response, cnt) => {
-									var r = (ResponseDryRun)response;
-									if (DataBus.GearboxInfo.GearboxType.AutomaticTransmission() &&
-										r.DeltaDragLoad.Value().IsSmallerOrEqual(-double.MaxValue / 20)) {
-										nanCount1++;
-									}
-
-									if (nanCount1 > 10) {
-										return true;
-									}
-
-									return r != null && !allowDistanceDecrease &&
-											!ds.IsEqual(r.Driver.OperatingPoint.SimulationDistance);
-								},
-								forceLineSearch: true);
-							return ComputeTimeInterval(retVal.Acceleration, retVal.SimulationDistance);
+										if (nanCount1 > 10) {
+											return true;
+										}
+
+										return r != null && !allowDistanceDecrease &&
+												!ds.IsEqual(r.Driver.OperatingPoint.SimulationDistance);
+									},
+									forceLineSearch: true);
+								return ComputeTimeInterval(retVal.Acceleration, retVal.SimulationDistance);
+							} catch (VectoException ve2) {
+								Log.Error(ve2);
+								return null;
+							}
 						}
+
 						break;
 
 				}
@@ -1450,6 +1463,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			}
 			CurrentState.Response = null;
 			DriverStrategy.CommitSimulationStep();
+			if (_previousGearboxDisengaged.HasValue) {
+				DataBus.GearboxCtl.DisengageGearbox = _previousGearboxDisengaged.Value;
+				_previousGearboxDisengaged = null;
+			}
 		}
 
 		public class DriverState
-- 
GitLab