diff --git a/VectoCore/FileIO/Reader/DataObjectAdaper/DeclarationDataAdapter.cs b/VectoCore/FileIO/Reader/DataObjectAdaper/DeclarationDataAdapter.cs index 9b6a591478ab7b9a820df9e5c3d2a4448e2b7c4a..0f0b1ab619c4d6a7cc2e086cb044d4882a116b17 100644 --- a/VectoCore/FileIO/Reader/DataObjectAdaper/DeclarationDataAdapter.cs +++ b/VectoCore/FileIO/Reader/DataObjectAdaper/DeclarationDataAdapter.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using System.Linq; using TUGraz.VectoCore.Configuration; @@ -181,22 +180,25 @@ namespace TUGraz.VectoCore.FileIO.Reader.DataObjectAdaper retVal.HasTorqueConverter = false; var axleGear = gearbox.Body.Gears.First(); - var lossMap = TransmissionLossMap.ReadFromFile(Path.Combine(gearbox.BasePath, axleGear.LossMap), axleGear.Ratio); - retVal.AxleGearData = new GearData { LossMap = lossMap, Ratio = axleGear.Ratio }; + var axleLossMap = TransmissionLossMap.ReadFromFile(Path.Combine(gearbox.BasePath, axleGear.LossMap), axleGear.Ratio); + retVal.AxleGearData = new GearData { LossMap = axleLossMap, Ratio = axleGear.Ratio, TorqueConverterActive = false }; retVal.Gears = gearbox.Body.Gears.Skip(1).Select((gear, i) => { - lossMap = TransmissionLossMap.ReadFromFile(Path.Combine(gearbox.BasePath, gear.LossMap), gear.Ratio); - EngineFullLoadCurve fullLoadCurve; - if (string.IsNullOrWhiteSpace(gear.FullLoadCurve) || gear.FullLoadCurve == "<NOFILE>") { - fullLoadCurve = engine.FullLoadCurve; - } else { - var gearFullLoad = FullLoadCurve.ReadFromFile(Path.Combine(gearbox.BasePath, gear.FullLoadCurve)); - fullLoadCurve = IntersectFullLoadCurves(gearFullLoad, engine.FullLoadCurve); - } + var gearLossMap = TransmissionLossMap.ReadFromFile(Path.Combine(gearbox.BasePath, gear.LossMap), gear.Ratio); + var gearFullLoad = (string.IsNullOrWhiteSpace(gear.FullLoadCurve) || gear.FullLoadCurve == "<NOFILE>") + ? engine.FullLoadCurve + : FullLoadCurve.ReadFromFile(Path.Combine(gearbox.BasePath, gear.FullLoadCurve)); + var fullLoadCurve = IntersectFullLoadCurves(gearFullLoad, engine.FullLoadCurve); var shiftPolygon = DeclarationData.Gearbox.ComputeShiftPolygon(fullLoadCurve, engine.IdleSpeed); return new KeyValuePair<uint, GearData>((uint)i + 1, - new GearData { LossMap = lossMap, ShiftPolygon = shiftPolygon, Ratio = gear.Ratio }); + new GearData { + LossMap = gearLossMap, + ShiftPolygon = shiftPolygon, + FullLoadCurve = gearFullLoad, + Ratio = gear.Ratio, + TorqueConverterActive = false + }); }).ToDictionary(kv => kv.Key, kv => kv.Value); return retVal; } @@ -205,12 +207,11 @@ namespace TUGraz.VectoCore.FileIO.Reader.DataObjectAdaper /// Intersects full load curves. /// </summary> /// <param name="curves">full load curves</param> - /// <returns>A combined full load curve with the minimum of all full load torques over all input curves.</returns> + /// <returns>A combined EngineFullLoadCurve with the minimum full load torque over all inputs curves.</returns> private static EngineFullLoadCurve IntersectFullLoadCurves(params FullLoadCurve[] curves) { - var entries = curves.SelectMany(curve => curve.FullLoadEntries) - .Select(entry => entry.EngineSpeed) - .OrderBy(x => x) + var entries = curves.SelectMany(curve => curve.FullLoadEntries, (curve, entry) => entry.EngineSpeed) + .OrderBy(engineSpeed => engineSpeed) .Distinct() .Select(engineSpeed => new FullLoadCurve.FullLoadCurveEntry { EngineSpeed = engineSpeed, diff --git a/VectoCore/Models/Connector/Ports/IResponse.cs b/VectoCore/Models/Connector/Ports/IResponse.cs index 7965878e35c78a1ab469a724a1814bab4221dbd5..d6d68d495dfab355caa637982c081eb2028d843b 100644 --- a/VectoCore/Models/Connector/Ports/IResponse.cs +++ b/VectoCore/Models/Connector/Ports/IResponse.cs @@ -12,6 +12,7 @@ namespace TUGraz.VectoCore.Models.Connector.Ports FailTimeInterval, DrivingCycleDistanceExceeded, DryRun, + GearShift } diff --git a/VectoCore/Models/SimulationComponent/Data/Gearbox/ShiftPolygon.cs b/VectoCore/Models/SimulationComponent/Data/Gearbox/ShiftPolygon.cs index f3cc051dc714c0360f77b9cafd87ce5662cf978e..f84847448cc28fa02763da4547c852ac1d07a63b 100644 --- a/VectoCore/Models/SimulationComponent/Data/Gearbox/ShiftPolygon.cs +++ b/VectoCore/Models/SimulationComponent/Data/Gearbox/ShiftPolygon.cs @@ -33,13 +33,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox List<ShiftPolygonEntry> entriesDown, entriesUp; if (HeaderIsValid(data.Columns)) { - entriesDown = CreateFromColumnNames(data, Fields.AngluarSpeedDown); + entriesDown = CreateFromColumnNames(data, Fields.AngularSpeedDown); entriesUp = CreateFromColumnNames(data, Fields.AngularSpeedUp); } else { var log = LogManager.GetLogger<ShiftPolygon>(); log.WarnFormat( "ShiftPolygon: Header Line is not valid. Expected: '{0}, {1}, {2}', Got: '{3}'. Falling back to column index", - Fields.Torque, Fields.AngularSpeedUp, Fields.AngluarSpeedDown, + Fields.Torque, Fields.AngularSpeedUp, Fields.AngularSpeedDown, string.Join(", ", data.Columns.Cast<DataColumn>().Select(c => c.ColumnName).Reverse())); entriesDown = CreateFromColumnIndizes(data, 1); entriesUp = CreateFromColumnIndizes(data, 2); @@ -60,7 +60,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox private static bool HeaderIsValid(DataColumnCollection columns) { return columns.Contains(Fields.Torque) && columns.Contains(Fields.AngularSpeedUp) && - columns.Contains((Fields.AngluarSpeedDown)); + columns.Contains((Fields.AngularSpeedDown)); } private static List<ShiftPolygonEntry> CreateFromColumnNames(DataTable data, string columnName) @@ -97,7 +97,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox /// <summary> /// [rpm] threshold for downshift /// </summary> - public const string AngluarSpeedDown = "downshift rpm"; + public const string AngularSpeedDown = "downshift rpm"; } public class ShiftPolygonEntry diff --git a/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs b/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs index 53dcf97ec378a712ac6c4b70fa4449f10f4eb01f..7d5e067941f5e50d25da0ca34899b238e5d005da 100644 --- a/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs +++ b/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs @@ -66,11 +66,48 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl IResponse ITnOutPort.Request(Second absTime, Second dt, NewtonMeter torque, PerSecond engineSpeed, bool dryRun) { - // todo check shiftpolygon for shifting - - // convert out data to in data - var inEngineSpeed = engineSpeed * CurrentGear.Ratio; - var inTorque = CurrentGear.LossMap.GearboxInTorque(inEngineSpeed, torque); + bool gearChanged; + PerSecond inEngineSpeed; + NewtonMeter inTorque; + + do { + gearChanged = false; + // calculate new inEngineSpeed and Torque for the current gear + inEngineSpeed = engineSpeed * CurrentGear.Ratio; + inTorque = CurrentGear.LossMap.GearboxInTorque(inEngineSpeed, torque); + + //todo: + // Data.TorqueReserve ... % TorqueReserver for GearSkipping and EarlyUpshift + // Data.ShiftTime ... minimal time between shift operations + // AT, MT, AMT .... different behaviour! + + // check if GearBox should shift up + if (_gear < Data.Gears.Count) { + var upSection = CurrentGear.ShiftPolygon.Upshift.GetSection(entry => entry.AngularSpeed < inEngineSpeed); + if (inEngineSpeed > upSection.Item2.AngularSpeed || + (inEngineSpeed > upSection.Item1.AngularSpeed && + (inTorque < upSection.Item1.Torque || inTorque < upSection.Item2.Torque))) { + _gear++; + gearChanged = true; + continue; + } + } + + // check if GearBox should shift down + if (_gear > 1) { + var downSection = CurrentGear.ShiftPolygon.Downshift.GetSection(entry => entry.AngularSpeed < inEngineSpeed); + if (inEngineSpeed < downSection.Item1.AngularSpeed || + (inEngineSpeed < downSection.Item2.AngularSpeed && + (inTorque > downSection.Item1.Torque || inTorque > downSection.Item2.Torque))) { + _gear--; + gearChanged = true; + } + } + } while (Data.SkipGears && gearChanged); + + if (gearChanged) { + return new ResponseGearShift { SimulationInterval = Data.TractionInterruption }; + } // check full load curve for overload/underload (mirrored) var maxTorque = CurrentGear.FullLoadCurve.FullLoadStationaryTorque(inEngineSpeed); @@ -115,4 +152,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl #endregion } + + internal class ResponseGearShift : AbstractResponse + { + public override ResponseType ResponseType + { + get { return ResponseType.GearShift; } + } + } } \ No newline at end of file