diff --git a/VectoCore/VectoCore/Configuration/Constants.cs b/VectoCore/VectoCore/Configuration/Constants.cs index 905a36cc0b16f694dd0df7bc41ea58c7de6f986c..cba7ea910b3815f7e131f0fe5a7a2edc40fdce43 100644 --- a/VectoCore/VectoCore/Configuration/Constants.cs +++ b/VectoCore/VectoCore/Configuration/Constants.cs @@ -140,7 +140,7 @@ namespace TUGraz.VectoCore.Configuration public const double ClutchClosingSpeedNorm = 0.065; - public static readonly MeterPerSecond ClutchDisengageWhenHaltingSpeed = 15.KMPHtoMeterPerSecond(); + public static readonly MeterPerSecond ClutchDisengageWhenHaltingSpeed = 10.KMPHtoMeterPerSecond(); public static readonly MeterPerSecond ATGearboxDisengageWhenHaltingSpeed = 5.KMPHtoMeterPerSecond(); diff --git a/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs b/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs index 5ea07c3dfc9ff40a82db8048911582d56dac1b4a..8d1f35e7334954fe24810951eb51dc4b760dcf36 100644 --- a/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs +++ b/VectoCore/VectoCore/Models/Declaration/DeclarationData.cs @@ -249,10 +249,10 @@ namespace TUGraz.VectoCore.Models.Declaration public static readonly KilogramSquareMeter Inertia = 0.SI<KilogramSquareMeter>(); public static readonly MeterPerSecond TruckMaxAllowedSpeed = 85.KMPHtoMeterPerSecond(); - public const double ShiftPolygonRPMMargin = 7; + public const double ShiftPolygonRPMMargin = 7; // % private const double ShiftPolygonEngineFldMargin = 0.98; - public static readonly Second MinTimeBetweenGearshifts = 2.SI<Second>(); + public static readonly Second MinTimeBetweenGearshifts = 1.5.SI<Second>(); public static readonly Second DownshiftAfterUpshiftDelay = 10.SI<Second>(); public static readonly Second UpshiftAfterDownshiftDelay = 10.SI<Second>(); public static readonly MeterPerSquareSecond UpshiftMinAcceleration = 0.1.SI<MeterPerSquareSecond>(); diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/ShiftPolygon.cs b/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/ShiftPolygon.cs index dc0f6ff3dee4192f74c54beb69f963507a0c7d8c..9b41a3a89c317a321258b886c7b0ba1beeb6c4a8 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/ShiftPolygon.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Data/Gearbox/ShiftPolygon.cs @@ -72,6 +72,25 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox return IsLeftOf(inAngularVelocity, inTorque, section); } + public bool IsBelowUpshiftCurve(NewtonMeter inTorque, PerSecond inAngularVelocity) + { + var section = Upshift.GetSection(entry => entry.AngularSpeed < inAngularVelocity); + if (section.Item2.AngularSpeed < inAngularVelocity) { + return false; + } + return IsLeftOf(inAngularVelocity, inTorque, section); + } + + public bool IsAboveDownshiftCurve(NewtonMeter inTorque, PerSecond inAngularVelocity) + { + var section = Downshift.GetSection(entry => entry.AngularSpeed < inAngularVelocity); + + if (section.Item2.AngularSpeed < inAngularVelocity) { + return true; + } + return IsRightOf(inAngularVelocity, inTorque, section); + } + public bool IsAboveUpshiftCurve(NewtonMeter inTorque, PerSecond inAngularVelocity) { var section = Upshift.GetSection(entry => entry.AngularSpeed < inAngularVelocity); @@ -154,5 +173,17 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox /// </summary> public PerSecond AngularSpeed { get; set; } } + + public NewtonMeter InterpolateDownshift(PerSecond inAngularVelocity) + { + var section = Downshift.GetSection(entry => entry.AngularSpeed < inAngularVelocity); + + if (section.Item1.AngularSpeed.IsEqual(section.Item2.AngularSpeed)) { + // vertical line + return double.MaxValue.SI<NewtonMeter>(); + } + return VectoMath.Interpolate(section.Item1.AngularSpeed, section.Item2.AngularSpeed, section.Item1.Torque, + section.Item2.Torque, inAngularVelocity); + } } } \ No newline at end of file diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/AMTShiftStrategy.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/AMTShiftStrategy.cs index ecbc353c9b0dd13ab822f91e331481bcbee96de8..f1700d328c94f2b9de7dd5718be8a83e0308fed9 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/AMTShiftStrategy.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/AMTShiftStrategy.cs @@ -115,8 +115,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl if (response.EngineSpeed > DataBus.EngineIdleSpeed && reserve >= ModelData.StartTorqueReserve) { _nextGear = gear; - _gearbox.LastUpshift = absTime; - _gearbox.LastDownshift = absTime; + //_gearbox.LastUpshift = absTime; + //_gearbox.LastDownshift = absTime; return gear; } } @@ -246,19 +246,32 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl NewtonMeter inTorque, PerSecond inAngularVelocity, uint currentGear) { // upshift - while (IsAboveUpShiftCurve(currentGear, inTorque, inAngularVelocity)) { + if (IsAboveUpShiftCurve(currentGear, inTorque, inAngularVelocity)) { currentGear++; - if (!SkipGears) { - break; - } - var tmpGear = Gearbox.Gear; - _gearbox.Gear = currentGear; - var response = (ResponseDryRun)_gearbox.Request(absTime, dt, outTorque, outAngularVelocity, true); - _gearbox.Gear = tmpGear; + while (SkipGears && currentGear < ModelData.Gears.Count) { + currentGear++; + var tmpGear = Gearbox.Gear; + _gearbox.Gear = currentGear; + var response = (ResponseDryRun)_gearbox.Request(absTime, dt, outTorque, outAngularVelocity, true); + _gearbox.Gear = tmpGear; - inAngularVelocity = ModelData.Gears[currentGear].Ratio * outAngularVelocity; - inTorque = response.ClutchPowerRequest / inAngularVelocity; + inAngularVelocity = response.EngineSpeed; //ModelData.Gears[currentGear].Ratio * outAngularVelocity; + inTorque = response.ClutchPowerRequest / inAngularVelocity; + + var maxTorque = VectoMath.Min(response.DynamicFullLoadPower / ((DataBus.EngineSpeed + response.EngineSpeed) / 2), + currentGear > 1 + ? ModelData.Gears[currentGear].ShiftPolygon.InterpolateDownshift(response.EngineSpeed) + : double.MaxValue.SI<NewtonMeter>()); + var reserve = 1 - inTorque / maxTorque; + + if (reserve >= ModelData.TorqueReserve && IsAboveDownShiftCurve(currentGear, inTorque, inAngularVelocity)) { + continue; + } + + currentGear--; + break; + } } // early up shift to higher gear --------------------------------------- @@ -291,18 +304,28 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl NewtonMeter inTorque, PerSecond inAngularVelocity, uint currentGear) { // down shift - while (IsBelowDownShiftCurve(currentGear, inTorque, inAngularVelocity)) { + if (IsBelowDownShiftCurve(currentGear, inTorque, inAngularVelocity)) { currentGear--; - if (!SkipGears) { + while (SkipGears && currentGear > 1) { + currentGear--; + var tmpGear = Gearbox.Gear; + _gearbox.Gear = currentGear; + var response = (ResponseDryRun)_gearbox.Request(absTime, dt, outTorque, outAngularVelocity, true); + _gearbox.Gear = tmpGear; + + inAngularVelocity = ModelData.Gears[currentGear].Ratio * outAngularVelocity; + inTorque = response.ClutchPowerRequest / inAngularVelocity; + var maxTorque = VectoMath.Min(response.DynamicFullLoadPower / ((DataBus.EngineSpeed + response.EngineSpeed) / 2), + currentGear > 1 + ? ModelData.Gears[currentGear].ShiftPolygon.InterpolateDownshift(response.EngineSpeed) + : double.MaxValue.SI<NewtonMeter>()); + var reserve = 1 - inTorque / maxTorque; + if (reserve >= ModelData.TorqueReserve && IsBelowUpShiftCurve(currentGear, inTorque, inAngularVelocity)) { + continue; + } + currentGear++; break; } - var tmpGear = Gearbox.Gear; - _gearbox.Gear = currentGear; - var response = (ResponseDryRun)_gearbox.Request(absTime, dt, outTorque, outAngularVelocity, true); - _gearbox.Gear = tmpGear; - - inAngularVelocity = ModelData.Gears[currentGear].Ratio * outAngularVelocity; - inTorque = response.ClutchPowerRequest / inAngularVelocity; } return currentGear; } diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs index 15508ae4b279afb73672461b8ae5bedd750646d7..318ea49f4c81b99997f13dbfe06fee0f02680f0c 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs @@ -626,6 +626,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl _idleStart = absTime; _lastEnginePower = _engine.PreviousState.EnginePower; } + if (_lastEnginePower == null) { + _lastEnginePower = _engine.PreviousState.EnginePower; + } IResponse retVal; var idleTime = absTime - _idleStart + dt; diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs index 4e64f73b20bc305da06f13dae89a85cafeceb26c..f51c925c2f5dc468f0bec641d0911ab878e3d119 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs @@ -177,10 +177,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl _engageTime = absTime + dt; } - if (DataBus.DriverBehavior == DrivingBehavior.Braking && DataBus.BrakePower.IsGreater(0) && outTorque < 0 && + if (DataBus.DriverBehavior == DrivingBehavior.Braking && (DataBus.BrakePower.IsGreater(0) || outTorque < 0) && DataBus.VehicleSpeed.IsSmaller(Constants.SimulationSettings.ClutchDisengageWhenHaltingSpeed)) { - _engageTime = absTime + dt; - Disengaged = true; + _engageTime = VectoMath.Max(_engageTime, absTime + dt); + return RequestGearDisengaged(absTime, dt, outTorque, outAngularVelocity, dryRun); } @@ -231,11 +231,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl if (dryRun) { // if gearbox is disengaged the 0[W]-line is the limit for drag and full load. + var delta = inTorque * avgInAngularVelocity; return new ResponseDryRun { Source = this, - GearboxPowerRequest = inTorque * avgInAngularVelocity, - DeltaDragLoad = inTorque * avgInAngularVelocity, - DeltaFullLoad = inTorque * avgInAngularVelocity, + GearboxPowerRequest = delta, + DeltaDragLoad = delta, + DeltaFullLoad = delta, }; } @@ -347,8 +348,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl if (response is ResponseSuccess && shiftAllowed) { var shiftRequired = _strategy.ShiftRequired(absTime, dt, outTorque, outAngularVelocity, inTorque, - response.EngineSpeed, - Gear, _engageTime); + response.EngineSpeed, Gear, _engageTime); if (shiftRequired) { _engageTime = absTime + ModelData.TractionInterruption; diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/ShiftStrategy.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/ShiftStrategy.cs index d4a37848dc4679956c1309664eeb0a5d64a199aa..f459ce7ab4bdfb74bbce3fb5cc5b0c119e7fd252 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/ShiftStrategy.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/ShiftStrategy.cs @@ -50,8 +50,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl public override IGearbox Gearbox { get { return _gearbox; } - set - { + set { var myGearbox = value as Gearbox; if (myGearbox == null) { throw new VectoException("This shift strategy can't handle gearbox of type {0}", value.GetType()); @@ -75,6 +74,15 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return ModelData.Gears[gear].ShiftPolygon.IsBelowDownshiftCurve(inTorque, inEngineSpeed); } + protected bool IsAboveDownShiftCurve(uint gear, NewtonMeter inTorque, PerSecond inEngineSpeed) + { + if (gear <= 1) { + return true; + } + return ModelData.Gears[gear].ShiftPolygon.IsAboveDownshiftCurve(inTorque, inEngineSpeed); + } + + /// <summary> /// Tests if the operating point is above the up-shift curve (=outside of shift curve). /// </summary> @@ -89,5 +97,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl } return ModelData.Gears[gear].ShiftPolygon.IsAboveUpshiftCurve(inTorque, inEngineSpeed); } + + protected bool IsBelowUpShiftCurve(uint gear, NewtonMeter inTorque, PerSecond inEngineSpeed) + { + if (gear >= ModelData.Gears.Count) { + return true; + } + return ModelData.Gears[gear].ShiftPolygon.IsBelowUpshiftCurve(inTorque, inEngineSpeed); + } } } \ No newline at end of file diff --git a/VectoCore/VectoCoreTest/Models/Declaration/ShiftPolygonTest.cs b/VectoCore/VectoCoreTest/Models/Declaration/ShiftPolygonTest.cs index 58d99663d8de1441a0133fd7739c9e0e2dc4bfce..9c3c38aff74e791160deb4daee68b2f250c14c27 100644 --- a/VectoCore/VectoCoreTest/Models/Declaration/ShiftPolygonTest.cs +++ b/VectoCore/VectoCoreTest/Models/Declaration/ShiftPolygonTest.cs @@ -457,7 +457,7 @@ namespace TUGraz.VectoCore.Tests.Models.Declaration }; engineData.FullLoadCurve.EngineData = engineData; - var gearboxData = new JSONGearboxDataV5(JSONInputDataFactory.ReadFile(Path.Combine(BasePath, gearboxFile)), + var gearboxData = new JSONGearboxDataV6(JSONInputDataFactory.ReadFile(Path.Combine(BasePath, gearboxFile)), Path.Combine(BasePath, gearboxFile)); var shiftPolygons = new List<ShiftPolygon>(); @@ -486,6 +486,20 @@ namespace TUGraz.VectoCore.Tests.Models.Declaration imageFile, DeclarationData.Gearbox.TruckMaxAllowedSpeed / rdyn.SI<Meter>() * axlegearRatio * gearboxData.Gears.Last().Ratio, upshiftOrig, downshiftTransformed); + var str = ""; + var g = 1; + foreach (var shiftPolygon in shiftPolygons) { + str += "Gear " + g + "\n"; + str += "downshift\n"; + foreach (var entry in shiftPolygon.Downshift) { + str += string.Format("{0} {1}\n", entry.AngularSpeed.AsRPM, entry.Torque.Value()); + } + str += "upshift\n"; + foreach (var entry in shiftPolygon.Upshift) { + str += string.Format("{0} {1}\n", entry.AngularSpeed.AsRPM, entry.Torque.Value()); + } + g++; + } } public static void ComputShiftPolygonPoints(int gear, FullLoadCurve fullLoadCurve, diff --git a/VectoCore/VectoCoreTest/Models/SimulationComponent/GearboxTest.cs b/VectoCore/VectoCoreTest/Models/SimulationComponent/GearboxTest.cs index b9b5cbdc53d07e5de336b313d61e877791a34be0..c5490509372da21b4d1afa51935bc88c5a683e88 100644 --- a/VectoCore/VectoCoreTest/Models/SimulationComponent/GearboxTest.cs +++ b/VectoCore/VectoCoreTest/Models/SimulationComponent/GearboxTest.cs @@ -536,7 +536,8 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent Altitude = 0.SI<Meter>(), VehicleMass = 10000.SI<Kilogram>(), ReducedMassWheels = 100.SI<Kilogram>(), - TotalMass = 19000.SI<Kilogram>() + TotalMass = 19000.SI<Kilogram>(), + EngineSpeed = n.SI<PerSecond>() }; var gearboxData = MockSimulationDataFactory.CreateGearboxDataFromFile(GearboxDataFile, EngineDataFile); var runData = GetDummyRunData(gearboxData);