From 16f0cd07128dfe85fb0b6b65bb4989c69ad18a8b Mon Sep 17 00:00:00 2001
From: Markus Quaritsch <markus.quaritsch@tugraz.at>
Date: Tue, 13 Oct 2015 10:31:59 +0200
Subject: [PATCH] - introduce new exception in case searching for an operating
 point gives no result - open the clutch if the vehicle's speed gets too low
 and the engine speed goes below idle speed

---
 VectoCore/Configuration/Constants.cs          |  2 ++
 .../Models/Connector/Ports/Impl/Response.cs   |  2 ++
 .../Models/SimulationComponent/Impl/Driver.cs | 34 ++++++++++++++-----
 .../SimulationComponent/Impl/Gearbox.cs       |  7 ++++
 4 files changed, 37 insertions(+), 8 deletions(-)

diff --git a/VectoCore/Configuration/Constants.cs b/VectoCore/Configuration/Constants.cs
index 525928ee18..e8f102d701 100644
--- a/VectoCore/Configuration/Constants.cs
+++ b/VectoCore/Configuration/Constants.cs
@@ -86,6 +86,8 @@ namespace TUGraz.VectoCore.Configuration
 			public static readonly PerSecond EngineIdlingSearchInterval = 10.SI<PerSecond>();
 
 			public const int EngineSearchLoopThreshold = 100;
+
+			public static readonly MeterPerSecond VehicleStopClutchDisengageSpeed = 10.KMPHtoMeterPerSecond();
 		}
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/Models/Connector/Ports/Impl/Response.cs b/VectoCore/Models/Connector/Ports/Impl/Response.cs
index 61b70770f5..f7bd2afe1e 100644
--- a/VectoCore/Models/Connector/Ports/Impl/Response.cs
+++ b/VectoCore/Models/Connector/Ports/Impl/Response.cs
@@ -87,4 +87,6 @@ namespace TUGraz.VectoCore.Models.Connector.Ports.Impl
 	}
 
 	internal class ResponseGearShift : AbstractResponse {}
+
+	internal class ResponseEngineSpeedTooLow : ResponseDryRun {}
 }
\ No newline at end of file
diff --git a/VectoCore/Models/SimulationComponent/Impl/Driver.cs b/VectoCore/Models/SimulationComponent/Impl/Driver.cs
index bf7e41b585..8573b2cc9e 100644
--- a/VectoCore/Models/SimulationComponent/Impl/Driver.cs
+++ b/VectoCore/Models/SimulationComponent/Impl/Driver.cs
@@ -148,8 +148,15 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 				});
 
 			if (retVal == null) {
-				// unhandled response (overload, delta > 0) - we need to search for a valid operating point..				
-				var nextOperatingPoint = SearchOperatingPoint(absTime, ds, gradient, operatingPoint.Acceleration, response);
+				// unhandled response (overload, delta > 0) - we need to search for a valid operating point..	
+
+				OperatingPoint nextOperatingPoint;
+				try {
+					nextOperatingPoint = SearchOperatingPoint(absTime, ds, gradient, operatingPoint.Acceleration, response);
+				} catch (VectoSimulationException) {
+					// in case of an exception during search the engine-speed got too low - gear disengaged, try roll action.
+					nextOperatingPoint = SearchOperatingPoint(absTime, ds, gradient, operatingPoint.Acceleration, response);
+				}
 
 				var limitedOperatingPoint = LimitAccelerationByDriverModel(nextOperatingPoint,
 					LimitationMode.LimitDecelerationDriver);
@@ -255,9 +262,14 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			//	return response;
 			//}
 
-			operatingPoint = SearchOperatingPoint(absTime, operatingPoint.SimulationDistance, gradient,
-				operatingPoint.Acceleration, response, coasting: true);
-
+			try {
+				operatingPoint = SearchOperatingPoint(absTime, operatingPoint.SimulationDistance, gradient,
+					operatingPoint.Acceleration, response, coasting: true);
+			} catch (VectoSimulationException) {
+				// in case of an exception during search the engine-speed got too low - gear disengaged, try roll action.
+				operatingPoint = SearchOperatingPoint(absTime, operatingPoint.SimulationDistance, gradient,
+					operatingPoint.Acceleration, response, coasting: true);
+			}
 			if (!ds.IsEqual(operatingPoint.SimulationDistance)) {
 				// vehicle is at low speed, coasting would lead to stop before ds is reached.
 				Log.Debug("SearchOperatingPoint reduced the max. distance: {0} -> {1}. Issue new request from driving cycle!",
@@ -488,7 +500,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 				var response =
 					(ResponseDryRun)
 						NextComponent.Request(absTime, operatingPoint.SimulationInterval, operatingPoint.Acceleration, gradient, true);
-				var delta = DataBus.ClutchClosed(absTime) ? response.DeltaDragLoad : response.GearboxPowerRequest;	
+				var delta = DataBus.ClutchClosed(absTime) ? response.DeltaDragLoad : response.GearboxPowerRequest;
 
 				if (delta.IsEqual(0.SI<Watt>(), Constants.SimulationSettings.EnginePowerSearchTolerance)) {
 					LogManager.EnableLogging();
@@ -516,7 +528,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			Log.Warn("Exceeded max iterations when searching for operating point!");
 			Log.Warn("exceeded: {0} ... {1}", ", ".Join(debug.Take(5)), ", ".Join(debug.Slice(-6)));
 			Log.Error("Failed to find operating point for breaking!");
-			throw new VectoSimulationException("Failed to find operating point for breaking!exceeded: {0} ... {1}",
+			throw new VectoSearchFailedException("Failed to find operating point for breaking!exceeded: {0} ... {1}",
 				", ".Join(debug.Take(5)), ", ".Join(debug.Slice(-6)));
 		}
 
@@ -607,6 +619,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 					(ResponseDryRun)NextComponent.Request(absTime, retVal.SimulationInterval, retVal.Acceleration, gradient, true);
 				delta = actionRoll ? response.GearboxPowerRequest : (coasting ? response.DeltaDragLoad : response.DeltaFullLoad);
 
+				if (response is ResponseEngineSpeedTooLow) {
+					LogManager.EnableLogging();
+					Log.Debug("Got EngineSpeedTooLow during SearchOperatingPoint. Aborting!");
+					throw new VectoSimulationException("EngineSpeed too low during search.");
+				}
+
 				if (delta.IsEqual(0.SI<Watt>(), Constants.SimulationSettings.EnginePowerSearchTolerance)) {
 					LogManager.EnableLogging();
 					Log.Debug("found operating point in {0} iterations. Engine Power req: {2}, Gearbox Power req: {3} delta: {1}",
@@ -622,7 +640,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			Log.Warn("exceeded: {0} ... {1}", ", ".Join(debug.Take(5).Select(x => x.delta)),
 				", ".Join(debug.Slice(-6).Select(x => x.delta)));
 			Log.Error("Failed to find operating point! absTime: {0}", absTime);
-			throw new VectoSimulationException("Failed to find operating point!  exceeded: {0} ... {1}",
+			throw new VectoSearchFailedException("Failed to find operating point!  exceeded: {0} ... {1}",
 				", ".Join(debug.Take(5).Select(x => x.delta)),
 				", ".Join(debug.Slice(-6).Select(x => x.delta)));
 		}
diff --git a/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs b/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs
index eedbdaeda2..2dafcc1493 100644
--- a/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs
+++ b/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs
@@ -293,6 +293,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			}
 
 			if (dryRun) {
+				if (inEngineSpeed < DataBus.EngineIdleSpeed && DataBus.VehicleSpeed < Constants.SimulationSettings.VehicleStopClutchDisengageSpeed) {
+					_disengaged = true;
+					_shiftTime = absTime + dt;
+					_strategy.Disengage(absTime, dt, outTorque, outAngularVelocity);
+					Log.Debug("EngineSpeed is below IdleSpeed, Gearbox disengage!");
+					return new ResponseEngineSpeedTooLow() { Source = this, GearboxPowerRequest = outTorque * outAngularVelocity };
+				}
 				var dryRunResponse = NextComponent.Request(absTime, dt, inTorque, inEngineSpeed, true);
 				dryRunResponse.GearboxPowerRequest = outTorque * outAngularVelocity;
 				return dryRunResponse;
-- 
GitLab