diff --git a/VectoCore/VectoCore/Models/SimulationComponent/IIdleController.cs b/VectoCore/VectoCore/Models/SimulationComponent/IIdleController.cs index fd039729ed80fb09c0d78ce92664178aea33d173..003c2f41f328225325f17099657ad602bfc3e3c5 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/IIdleController.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/IIdleController.cs @@ -29,6 +29,7 @@ * Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology */ +using TUGraz.VectoCommon.Utils; using TUGraz.VectoCore.Models.Connector.Ports; namespace TUGraz.VectoCore.Models.SimulationComponent @@ -38,5 +39,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent ITnOutPort RequestPort { set; } void Reset(); + void ActivateDoubleClutch(Second shiftTime, PerSecond targetVelocity); } } \ No newline at end of file diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs index d8e4174e5e03903da4204ca1faffd13448e68714..f198705b6684016976d9405e52db7c1edc3a2a2b 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs @@ -478,28 +478,60 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl protected class CombustionEngineIdleController : LoggingObject, IIdleController { - protected readonly double PeDropSlope = -5; - protected readonly double PeDropOffset = 1.0; + private readonly double PeDropSlope = -5; + private readonly double PeDropOffset = 1.0; - protected readonly CombustionEngine Engine; + private readonly CombustionEngine _engine; - protected Second IdleStart; - protected Watt LastEnginePower; + private Second _idleStart; + private Watt _lastEnginePower; + private PerSecond _targetVelocity; + private bool _doubleClutch; + private PerSquareSecond _velocitySlope; + + public ITnOutPort RequestPort { private get; set; } public CombustionEngineIdleController(CombustionEngine combustionEngine) { - Engine = combustionEngine; + _engine = combustionEngine; } - public ITnOutPort RequestPort { private get; set; } + public IResponse Initialize(NewtonMeter outTorque, PerSecond outAngularVelocity) + { + return new ResponseSuccess() { Source = this }; + } public void Reset() { - IdleStart = null; + _idleStart = null; + _doubleClutch = false; + _targetVelocity = null; + _velocitySlope = null; + } + + public void ActivateDoubleClutch(Second shiftTime, PerSecond targetVelocity) + { + if (shiftTime.IsEqual(0)) + // todo mk20161205: move default shift time to simulation parameters + shiftTime = 0.7.SI<Second>(); + + _velocitySlope = (_targetVelocity - _engine.PreviousState.EngineSpeed) / shiftTime; + + _doubleClutch = true; } public IResponse Request(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, bool dryRun = false) + { + if (_doubleClutch) + return RequestDoubleClutch(absTime, dt, outTorque, outAngularVelocity, dryRun); + else { + return RequestIdling(absTime, dt, outTorque, outAngularVelocity, dryRun); + } + } + + private IResponse RequestDoubleClutch(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, + bool dryRun = false) { if (outAngularVelocity != null) { throw new VectoException("IdleController can only handle idle requests, i.e. angularVelocity == null!"); @@ -507,24 +539,68 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl if (!outTorque.IsEqual(0)) { throw new VectoException("Torque has to be 0 for idle requests!"); } - if (IdleStart == null) { - IdleStart = absTime; - LastEnginePower = Engine.PreviousState.EnginePower; + if (_idleStart == null) { + _idleStart = absTime; + } + + var nextAngularSpeed = (_velocitySlope * dt + _engine.PreviousState.EngineSpeed) + .LimitTo(_engine.ModelData.IdleSpeed, _engine.EngineRatedSpeed); + + var retVal = RequestPort.Request(absTime, dt, outTorque, nextAngularSpeed); + retVal.Switch(). + Case<ResponseSuccess>(). + Case<ResponseUnderload>(r => { + var angularSpeed = SearchAlgorithm.Search(nextAngularSpeed, r.Delta, + Constants.SimulationSettings.EngineIdlingSearchInterval, + getYValue: result => ((ResponseDryRun)result).DeltaDragLoad, + evaluateFunction: n => RequestPort.Request(absTime, dt, outTorque, n, true), + criterion: result => ((ResponseDryRun)result).DeltaDragLoad.Value()); + Log.Debug("Found operating point for idling. absTime: {0}, dt: {1}, torque: {2}, angularSpeed: {3}", absTime, dt, + outTorque, angularSpeed); + retVal = RequestPort.Request(absTime, dt, outTorque, angularSpeed); + }). + Case<ResponseOverload>(r => { + var angularSpeed = SearchAlgorithm.Search(nextAngularSpeed, r.Delta, + -Constants.SimulationSettings.EngineIdlingSearchInterval, + getYValue: result => ((ResponseDryRun)result).DeltaFullLoad, + evaluateFunction: n => RequestPort.Request(absTime, dt, outTorque, n, true), + criterion: result => ((ResponseDryRun)result).DeltaFullLoad.Value()); + Log.Debug("Found operating point for idling. absTime: {0}, dt: {1}, torque: {2}, angularSpeed: {3}", absTime, dt, + outTorque, angularSpeed); + retVal = RequestPort.Request(absTime, dt, outTorque, angularSpeed); + }). + Default(r => { throw new UnexpectedResponseException("searching Idling point", r); }); + + return retVal; + } + + private IResponse RequestIdling(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, + bool dryRun = false) + { + if (outAngularVelocity != null) { + throw new VectoException("IdleController can only handle idle requests, i.e. angularVelocity == null!"); + } + if (!outTorque.IsEqual(0)) { + throw new VectoException("Torque has to be 0 for idle requests!"); + } + if (_idleStart == null) { + _idleStart = absTime; + _lastEnginePower = _engine.PreviousState.EnginePower; } IResponse retVal; - var idleTime = absTime - IdleStart + dt; - var prevEngineSpeed = Engine.PreviousState.EngineSpeed; - var dragLoad = Engine.ModelData.FullLoadCurve.DragLoadStationaryPower(prevEngineSpeed); + var idleTime = absTime - _idleStart + dt; + var prevEngineSpeed = _engine.PreviousState.EngineSpeed; + var dragLoad = _engine.ModelData.FullLoadCurve.DragLoadStationaryPower(prevEngineSpeed); - var nextEnginePower = (LastEnginePower - dragLoad) * VectoMath.Max(idleTime.Value() * PeDropSlope + PeDropOffset, 0) + - dragLoad; + var nextEnginePower = (_lastEnginePower - dragLoad) * + VectoMath.Max(idleTime.Value() * PeDropSlope + PeDropOffset, 0) + dragLoad; var auxDemandResponse = RequestPort.Request(absTime, dt, outTorque, prevEngineSpeed, true); var deltaEnginePower = nextEnginePower - (auxDemandResponse.AuxiliariesPowerDemand ?? 0.SI<Watt>()); var deltaTorque = deltaEnginePower / prevEngineSpeed; - var deltaAngularSpeed = deltaTorque / Engine.ModelData.Inertia * dt; + var deltaAngularSpeed = deltaTorque / _engine.ModelData.Inertia * dt; var nextAngularSpeed = prevEngineSpeed; if (deltaAngularSpeed > 0) { @@ -532,10 +608,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return retVal; } - nextAngularSpeed = prevEngineSpeed + deltaAngularSpeed; - if (nextAngularSpeed < Engine.ModelData.IdleSpeed) { - nextAngularSpeed = Engine.ModelData.IdleSpeed; - } + nextAngularSpeed = (prevEngineSpeed + deltaAngularSpeed) + .LimitTo(_engine.ModelData.IdleSpeed, _engine.EngineRatedSpeed); retVal = RequestPort.Request(absTime, dt, outTorque, nextAngularSpeed); retVal.Switch(). @@ -554,11 +628,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return retVal; } - - public IResponse Initialize(NewtonMeter outTorque, PerSecond outAngularVelocity) - { - return new ResponseSuccess() { Source = this }; - } } } } \ No newline at end of file diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/IdleControllerSwitcher.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/IdleControllerSwitcher.cs index a43f2451612f3742cfa81e09602db03285d0cba3..9524923fe01f9c7ffd593882d287e9276a59d30e 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/IdleControllerSwitcher.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/IdleControllerSwitcher.cs @@ -33,7 +33,6 @@ using System; using TUGraz.VectoCommon.Models; using TUGraz.VectoCommon.Utils; using TUGraz.VectoCore.Models.Connector.Ports; -using TUGraz.VectoCore.Models.Simulation; using TUGraz.VectoCore.OutputData; namespace TUGraz.VectoCore.Models.SimulationComponent.Impl @@ -80,6 +79,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl _currentController = _idleController; } + public void ActivateDoubleClutch(Second shiftTime, PerSecond targetVelocity) + { + _currentController.ActivateDoubleClutch(shiftTime, targetVelocity); + } + public void ActivatePTO() { _currentController = _ptoController; diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/PTOCycleController.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/PTOCycleController.cs index c50fa202339ba2837e0313d2e1c37e9f4da27766..9a71eea3129963a53f5b4f2f280aa8b13db93e64 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/PTOCycleController.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/PTOCycleController.cs @@ -90,6 +90,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl IdleStart = null; } + public void ActivateDoubleClutch(Second shiftTime, PerSecond targetVelocity) + { + // todo mk 20161205: use double clutching during pto controller? + return; + } + public Second GetNextCycleTime() { if (RightSample.Current == null) diff --git a/VectoCore/VectoCoreTest/Utils/MockIdleController.cs b/VectoCore/VectoCoreTest/Utils/MockIdleController.cs index 513cdf225fe5be8984e716c77f9a2283759a8136..ced58419e3af43934c06e9c8fcfc1fe2516e61dd 100644 --- a/VectoCore/VectoCoreTest/Utils/MockIdleController.cs +++ b/VectoCore/VectoCoreTest/Utils/MockIdleController.cs @@ -39,23 +39,21 @@ namespace TUGraz.VectoCore.Tests.Utils { public class MockIdleController : IIdleController { - public IResponse Request(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, bool dryRun = false) + public IResponse Request(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, + bool dryRun = false) { - //throw new System.NotImplementedException(); return new ResponseSuccess(); } public IResponse Initialize(NewtonMeter outTorque, PerSecond outAngularVelocity) { - //throw new System.NotImplementedException(); return new ResponseSuccess(); } public ITnOutPort RequestPort { get; set; } - public void Reset() - { - //throw new System.NotImplementedException(); - } + public void Reset() {} + + public void ActivateDoubleClutch(Second shiftTime, PerSecond targetVelocity) {} } } \ No newline at end of file