diff --git a/VectoCore/Models/SimulationComponent/IShiftStrategy.cs b/VectoCore/Models/SimulationComponent/IShiftStrategy.cs index 55b5ee590408d50d84be52e7d66170494f1393c7..6b1c6f8e05606830e0d775f1594ce3d3e2516b9a 100644 --- a/VectoCore/Models/SimulationComponent/IShiftStrategy.cs +++ b/VectoCore/Models/SimulationComponent/IShiftStrategy.cs @@ -5,10 +5,50 @@ namespace TUGraz.VectoCore.Models.SimulationComponent { public interface IShiftStrategy { + /// <summary> + /// Checks if a shift operation is required. + /// </summary> + /// <param name="gear">The current gear.</param> + /// <param name="torque">The torque.</param> + /// <param name="angularSpeed">The angular speed.</param> + /// <returns></returns> bool ShiftRequired(uint gear, NewtonMeter torque, PerSecond angularSpeed); - uint InitGear(NewtonMeter torque, PerSecond angularSpeed); - uint Engage(NewtonMeter outTorque, PerSecond outEngineSpeed, bool skipGears); - void Disengage(NewtonMeter outTorque, PerSecond outEngineSpeed); + + /// <summary> + /// Returns an appropriate starting gear. + /// </summary> + /// <param name="absTime">The abs time.</param> + /// <param name="dt">The dt.</param> + /// <param name="torque">The torque.</param> + /// <param name="outEngineSpeed">The angular speed.</param> + /// <returns></returns> + uint InitGear(Second absTime, Second dt, NewtonMeter torque, PerSecond outEngineSpeed); + + /// <summary> + /// Engages a gear + /// </summary> + /// <param name="absTime">The abs time.</param> + /// <param name="dt">The dt.</param> + /// <param name="outTorque">The out torque.</param> + /// <param name="outEngineSpeed">The out engine speed.</param> + /// <returns></returns> + uint Engage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outEngineSpeed); + + /// <summary> + /// Disengages a gear. + /// </summary> + /// <param name="absTime">The abs time.</param> + /// <param name="dt">The dt.</param> + /// <param name="outTorque">The out torque.</param> + /// <param name="outEngineSpeed">The out engine speed.</param> + void Disengage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outEngineSpeed); + + /// <summary> + /// Gets or sets the gearbox. + /// </summary> + /// <value> + /// The gearbox. + /// </value> Gearbox Gearbox { get; set; } } } \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs b/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs index 0ea75d234846339afefb1dce314eed708076c759..b9edeed54d218e6f02ad55f87fa66d7ccb990092 100644 --- a/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs +++ b/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs @@ -8,10 +8,6 @@ using TUGraz.VectoCore.Models.Simulation.DataBus; using TUGraz.VectoCore.Models.SimulationComponent.Data; using TUGraz.VectoCore.Utils; -// TODO: -// * EarlyUpshift (shift before outside of up-shift curve if outTorque reserve for the next higher gear is fullfilled) -// * SkipGears (when already shifting to next gear, check if outTorque reserve is fullfilled for the overnext gear and eventually shift to it) - namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { public class Gearbox : VectoSimulationComponent, IGearbox, ITnOutPort, ITnInPort, IClutchInfo @@ -36,7 +32,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl /// </summary> private Second _shiftTime = double.NegativeInfinity.SI<Second>(); - /// <summary> /// True if gearbox is disengaged (no gear is set). /// </summary> @@ -57,7 +52,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl /// </summary> private PerSecond _previousInEnginespeed = 0.SI<PerSecond>(); - public bool ClutchClosed(Second absTime) { return _shiftTime.IsSmaller(absTime); @@ -106,10 +100,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl public IResponse Initialize(NewtonMeter torque, PerSecond engineSpeed) { + var response = NextComponent.Initialize(torque, engineSpeed); + _shiftTime = double.NegativeInfinity.SI<Second>(); - Gear = _strategy.InitGear(torque, engineSpeed); - _disengaged = false; - return NextComponent.Initialize(torque, engineSpeed); + Gear = 0; //_strategy.InitGear(torque, engineSpeed); + _disengaged = true; + + return response; } /// <summary> @@ -180,9 +177,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl }; } - if (DataBus.VehicleSpeed.IsEqual(0)) { - Gear = _strategy.Engage(outTorque, outEngineSpeed, Data.SkipGears); - } + //if (DataBus.VehicleSpeed.IsEqual(0)) { + // Gear = _strategy.Engage(outTorque, outEngineSpeed, Data.SkipGears); + //} var response = NextComponent.Request(absTime, dt, 0.SI<NewtonMeter>(), null); response.GearboxPowerRequest = outTorque * outEngineSpeed; @@ -204,8 +201,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { // Set a Gear if no gear was set if (_disengaged) { - Gear = _strategy.Engage(outTorque, outEngineSpeed, Data.SkipGears); _disengaged = false; + Gear = DataBus.VehicleSpeed.IsEqual(0) + ? _strategy.InitGear(absTime, dt, outTorque, outEngineSpeed) // initGear if speed was 0 + : _strategy.Engage(absTime, dt, outTorque, outEngineSpeed); + Log.Debug("Gearbox engaged gear {0}", Gear); } @@ -233,13 +233,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl if (isShiftAllowed && _strategy.ShiftRequired(Gear, inTorque, inEngineSpeed)) { _shiftTime = absTime + Data.TractionInterruption; + Log.Debug("Gearbox is shifting. absTime: {0}, dt: {1}, shiftTime: {2}, out: ({3}, {4}), in: ({5}, {6})", absTime, dt, + _shiftTime, outTorque, outEngineSpeed, inTorque, inEngineSpeed); + _disengaged = true; - _strategy.Disengage(outTorque, outEngineSpeed); + _strategy.Disengage(absTime, dt, outTorque, outEngineSpeed); Log.Info("Gearbox disengaged"); - - Log.Debug("Gearbox is shifting. absTime: {0}, shiftTime: {1}, outTorque:{2}, outEngineSpeed: {3}", - absTime, _shiftTime, outTorque, outEngineSpeed); - + return new ResponseGearShift { Source = this, SimulationInterval = Data.TractionInterruption, diff --git a/VectoCore/Models/SimulationComponent/Impl/ShiftStrategy.cs b/VectoCore/Models/SimulationComponent/Impl/ShiftStrategy.cs index dce629977e008c394530627105b7e4df699d21ad..7239eb8c0850b2beab29ec40d6e665f409e5a198 100644 --- a/VectoCore/Models/SimulationComponent/Impl/ShiftStrategy.cs +++ b/VectoCore/Models/SimulationComponent/Impl/ShiftStrategy.cs @@ -1,16 +1,20 @@ -using TUGraz.VectoCore.Exceptions; +using System; +using TUGraz.VectoCore.Models.Connector.Ports.Impl; using TUGraz.VectoCore.Models.SimulationComponent.Data; using TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox; using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { + // TODO: + // * EarlyUpshift (shift before outside of up-shift curve if outTorque reserve for the next higher gear is fullfilled) + public abstract class ShiftStrategy : IShiftStrategy { - public abstract uint Engage(NewtonMeter torque, PerSecond angularSpeed, bool skipGears); - public abstract void Disengage(NewtonMeter outTorque, PerSecond outEngineSpeed); + public abstract uint Engage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outEngineSpeed); + public abstract void Disengage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outEngineSpeed); public abstract bool ShiftRequired(uint gear, NewtonMeter torque, PerSecond angularSpeed); - public abstract uint InitGear(NewtonMeter torque, PerSecond angularSpeed); + public abstract uint InitGear(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outEngineSpeed); protected GearboxData Data; public Gearbox Gearbox { get; set; } @@ -24,7 +28,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl /// <summary> /// Tests if the gearbox should shift down. /// </summary> - protected bool ShouldShiftDown(uint gear, NewtonMeter inTorque, PerSecond inEngineSpeed) + protected virtual bool IsBelowDownShiftCurve(uint gear, NewtonMeter inTorque, PerSecond inEngineSpeed) { if (gear <= 1) { return false; @@ -37,7 +41,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl /// <summary> /// Tests if the gearbox should shift up. /// </summary> - protected bool ShouldShiftUp(uint gear, NewtonMeter inTorque, PerSecond inEngineSpeed) + protected virtual bool IsAboveUpShiftCurve(uint gear, NewtonMeter inTorque, PerSecond inEngineSpeed) { if (gear >= Data.Gears.Count) { return false; @@ -72,56 +76,55 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl public class AMTShiftStrategy : ShiftStrategy { - protected uint LastGear; + protected uint PreviousGear; public AMTShiftStrategy(GearboxData data) : base(data) { - LastGear = 1; + PreviousGear = 1; } - public uint GetGear(uint gear, NewtonMeter outTorque, PerSecond outEngineSpeed, bool skipGears) + private uint GetGear(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outEngineSpeed, bool skipGears, + double torqueReserve) { - var loopCount = Data.Gears.Count; // protection against infinite loops - do { - var inEngineSpeed = outEngineSpeed * Data.Gears[gear].Ratio; - var inTorque = Data.Gears[gear].LossMap.GearboxInTorque(inEngineSpeed, outTorque); - if (ShouldShiftUp(gear, inTorque, inEngineSpeed)) { - gear++; - continue; - } + var maxGear = (uint)(skipGears ? Data.Gears.Count : Math.Min(PreviousGear + 1, Data.Gears.Count)); + var minGear = skipGears ? 1 : Math.Max(PreviousGear - 1, 1); - if (ShouldShiftDown(gear, inTorque, inEngineSpeed)) { - gear--; - continue; - } - break; - } while (skipGears && loopCount-- > 0); + for (var gear = maxGear; gear > minGear; gear--) { + Gearbox.Gear = gear; + var response = (ResponseDryRun)Gearbox.Request(absTime, dt, outTorque, outEngineSpeed, true); + var currentPower = response.EnginePowerRequest; - if (gear == 0) { - throw new VectoSimulationException("Could not find gear! outTorque: {0}, outEngineSpeed: {1}, skipGears: {2}", - outTorque, outEngineSpeed, skipGears); + var fullLoadPower = currentPower - response.DeltaFullLoad; + var reserve = 1 - (currentPower / fullLoadPower).Cast<Scalar>(); + + var inAngularSpeed = outEngineSpeed * Data.Gears[gear].Ratio; + var inTorque = currentPower / inAngularSpeed; + if (!IsBelowDownShiftCurve(gear, inTorque, inAngularSpeed) && reserve >= torqueReserve) { + return gear; + } } - return gear; + return minGear; } - public override uint Engage(NewtonMeter outTorque, PerSecond outEngineSpeed, bool skipGears) + public override uint Engage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outEngineSpeed) { - return GetGear(LastGear, outTorque, outEngineSpeed, skipGears); + return GetGear(absTime, dt, outTorque, outEngineSpeed, Data.SkipGears, Data.TorqueReserve); } - public override void Disengage(NewtonMeter outTorque, PerSecond outEngineSpeed) + public override void Disengage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outEngineSpeed) { - LastGear = GetGear(Gearbox.Gear, outTorque, outEngineSpeed, Data.SkipGears); + PreviousGear = GetGear(absTime, dt, outTorque, outEngineSpeed, Data.SkipGears, Data.TorqueReserve); } public override bool ShiftRequired(uint gear, NewtonMeter torque, PerSecond angularSpeed) { - return ShouldShiftDown(gear, torque, angularSpeed) || ShouldShiftUp(gear, torque, angularSpeed); + return IsBelowDownShiftCurve(gear, torque, angularSpeed) || IsAboveUpShiftCurve(gear, torque, angularSpeed); } - public override uint InitGear(NewtonMeter torque, PerSecond angularSpeed) + + public override uint InitGear(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outEngineSpeed) { - return Engage(torque, angularSpeed, true); + return GetGear(absTime, dt, outTorque, outEngineSpeed, true, Data.StartTorqueReserve); } } @@ -130,12 +133,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { public MTShiftStrategy(GearboxData data) : base(data) {} - public override uint Engage(NewtonMeter torque, PerSecond angularSpeed, bool skipGears) + public override uint Engage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outEngineSpeed) { throw new System.NotImplementedException(); } - public override void Disengage(NewtonMeter outTorque, PerSecond outEngineSpeed) + public override void Disengage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outEngineSpeed) { throw new System.NotImplementedException(); } @@ -145,7 +148,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl throw new System.NotImplementedException(); } - public override uint InitGear(NewtonMeter torque, PerSecond angularSpeed) + public override uint InitGear(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outEngineSpeed) { throw new System.NotImplementedException(); } @@ -156,12 +159,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { public ATShiftStrategy(GearboxData data) : base(data) {} - public override uint Engage(NewtonMeter torque, PerSecond angularSpeed, bool skipGears) + public override uint Engage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outEngineSpeed) { throw new System.NotImplementedException(); } - public override void Disengage(NewtonMeter outTorque, PerSecond outEngineSpeed) + public override void Disengage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outEngineSpeed) { throw new System.NotImplementedException(); } @@ -171,7 +174,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl throw new System.NotImplementedException(); } - public override uint InitGear(NewtonMeter torque, PerSecond angularSpeed) + public override uint InitGear(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outEngineSpeed) { throw new System.NotImplementedException(); }