diff --git a/VectoCore/InputData/Reader/DrivingCycleDataReader.cs b/VectoCore/InputData/Reader/DrivingCycleDataReader.cs index 22e440efc8e32c37b6663118e1e526c93dab1a7a..87f32d1f03eaf09c8a95eaf0599fe5e5cd3a6721 100644 --- a/VectoCore/InputData/Reader/DrivingCycleDataReader.cs +++ b/VectoCore/InputData/Reader/DrivingCycleDataReader.cs @@ -289,8 +289,8 @@ namespace TUGraz.VectoCore.InputData.Reader RoadGradient = VectoMath.InclinationToAngle(row.ParseDoubleOrGetDefault(Fields.RoadGradient) / 100.0), StoppingTime = row.ParseDouble(Fields.StoppingTime).SI<Second>(), AdditionalAuxPowerDemand = row.ParseDoubleOrGetDefault(Fields.AdditionalAuxPowerDemand).SI().Kilo.Watt.Cast<Watt>(), - EngineSpeed = row.ParseDoubleOrGetDefault(Fields.EngineSpeed).RPMtoRad(), - Gear = row.ParseDoubleOrGetDefault(Fields.Gear), + AngularVelocity = row.ParseDoubleOrGetDefault(Fields.EngineSpeed).RPMtoRad(), + Gear = (uint)row.ParseDoubleOrGetDefault(Fields.Gear), AirSpeedRelativeToVehicle = row.ParseDoubleOrGetDefault(Fields.AirSpeedRelativeToVehicle).KMPHtoMeterPerSecond(), WindYawAngle = row.ParseDoubleOrGetDefault(Fields.WindYawAngle), AuxiliarySupplyPower = AuxSupplyPowerReader.Read(row) @@ -359,8 +359,8 @@ namespace TUGraz.VectoCore.InputData.Reader RoadGradientPercent = row.ParseDoubleOrGetDefault(Fields.RoadGradient), RoadGradient = VectoMath.InclinationToAngle(row.ParseDoubleOrGetDefault(Fields.RoadGradient) / 100.0), AdditionalAuxPowerDemand = row.ParseDoubleOrGetDefault(Fields.AdditionalAuxPowerDemand).SI().Kilo.Watt.Cast<Watt>(), - Gear = row.ParseDoubleOrGetDefault(Fields.Gear), - EngineSpeed = row.ParseDoubleOrGetDefault(Fields.EngineSpeed).RPMtoRad(), + Gear = (uint)row.ParseDoubleOrGetDefault(Fields.Gear), + AngularVelocity = row.ParseDoubleOrGetDefault(Fields.EngineSpeed).RPMtoRad(), AirSpeedRelativeToVehicle = row.ParseDoubleOrGetDefault(Fields.AirSpeedRelativeToVehicle).KMPHtoMeterPerSecond(), WindYawAngle = row.ParseDoubleOrGetDefault(Fields.WindYawAngle), AuxiliarySupplyPower = AuxSupplyPowerReader.Read(row) @@ -426,7 +426,7 @@ namespace TUGraz.VectoCore.InputData.Reader var absTime = 0.SI<Second>(); foreach (DataRow row in table.Rows) { var entry = new DrivingCycleData.DrivingCycleEntry { - EngineSpeed = row.ParseDoubleOrGetDefault(Fields.EngineSpeed).RPMtoRad(), + AngularVelocity = row.ParseDoubleOrGetDefault(Fields.EngineSpeed).RPMtoRad(), AdditionalAuxPowerDemand = row.ParseDoubleOrGetDefault(Fields.AdditionalAuxPowerDemand).SI().Kilo.Watt.Cast<Watt>(), AuxiliarySupplyPower = AuxSupplyPowerReader.Read(row) @@ -436,13 +436,13 @@ namespace TUGraz.VectoCore.InputData.Reader if (row.Field<string>(Fields.EngineTorque).Equals("<DRAG>")) { entry.Drag = true; } else { - entry.EngineTorque = row.ParseDouble(Fields.EngineTorque).SI<NewtonMeter>(); + entry.Torque = row.ParseDouble(Fields.EngineTorque).SI<NewtonMeter>(); } } else { if (row.Field<string>(Fields.EnginePower).Equals("<DRAG>")) { entry.Drag = true; } else { - entry.EngineTorque = row.ParseDouble(Fields.EnginePower).SI().Kilo.Watt.Cast<Watt>() / entry.EngineSpeed; + entry.Torque = row.ParseDouble(Fields.EnginePower).SI().Kilo.Watt.Cast<Watt>() / entry.AngularVelocity; } } entry.Time = absTime; @@ -506,8 +506,8 @@ namespace TUGraz.VectoCore.InputData.Reader var entries = table.Rows.Cast<DataRow>().Select(row => new DrivingCycleData.DrivingCycleEntry { Time = row.ParseDouble(Fields.Time).SI<Second>(), PWheel = row.ParseDouble(Fields.PWheel).SI().Kilo.Watt.Cast<Watt>(), - Gear = row.ParseDouble(Fields.Gear), - EngineSpeed = row.ParseDouble(Fields.EngineSpeed).RPMtoRad(), + Gear = (uint)row.ParseDouble(Fields.Gear), + AngularVelocity = row.ParseDouble(Fields.EngineSpeed).RPMtoRad(), AdditionalAuxPowerDemand = row.ParseDouble(Fields.AdditionalAuxPowerDemand).SI().Kilo.Watt.Cast<Watt>(), }).ToArray(); @@ -553,7 +553,7 @@ namespace TUGraz.VectoCore.InputData.Reader Time = row.ParseDouble(Fields.Time).SI<Second>(), VehicleTargetSpeed = row.ParseDouble(Fields.VehicleSpeed).KMPHtoMeterPerSecond(), RoadGradient = VectoMath.InclinationToAngle(row.ParseDoubleOrGetDefault(Fields.RoadGradient) / 100.0), - Gear = row.ParseDouble(Fields.Gear), + Gear = (uint)row.ParseDouble(Fields.Gear), AdditionalAuxPowerDemand = row.ParseDouble(Fields.AdditionalAuxPowerDemand).SI().Kilo.Watt.Cast<Watt>(), }).ToArray(); diff --git a/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs b/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs index d0fe36fbed61cb232102698d04fc105a8dc11180..03246ac05136ef6a61e150c34795d6e48ec02941 100644 --- a/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs +++ b/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs @@ -101,8 +101,8 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl modContainer.WriteModalResults = WriteModalResults; var current = i++; var builder = new PowertrainBuilder(modContainer, (writer, mass, loading) => - SumData.Write(d.IsEngineOnly, modContainer, d.JobName, string.Format("{0}-{1}", JobNumber, current), - d.Cycle.Name + Constants.FileExtensions.CycleFile, mass, loading)); + SumData.Write(d.IsEngineOnly, modContainer, d.JobName, string.Format("{0}-{1}", JobNumber, current), + d.Cycle.Name + Constants.FileExtensions.CycleFile, mass, loading)); VectoRun run; diff --git a/VectoCore/Models/SimulationComponent/Data/DrivingCycleData.cs b/VectoCore/Models/SimulationComponent/Data/DrivingCycleData.cs index 165c3c641a7e44025face790139ea9980c185c7b..f47ce7767a89cf397c7bcc125fbe05a49320d3fc 100644 --- a/VectoCore/Models/SimulationComponent/Data/DrivingCycleData.cs +++ b/VectoCore/Models/SimulationComponent/Data/DrivingCycleData.cs @@ -50,12 +50,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data RoadGradient = entry.RoadGradient; Altitude = entry.Altitude; StoppingTime = entry.StoppingTime; - EngineSpeed = entry.EngineSpeed; + AngularVelocity = entry.AngularVelocity; Gear = entry.Gear; AdditionalAuxPowerDemand = entry.AdditionalAuxPowerDemand; AirSpeedRelativeToVehicle = entry.AirSpeedRelativeToVehicle; WindYawAngle = entry.WindYawAngle; - EngineTorque = entry.EngineTorque; + Torque = entry.Torque; Drag = entry.Drag; AuxiliarySupplyPower = new Dictionary<string, Watt>(entry.AuxiliarySupplyPower); } @@ -104,12 +104,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data /// <summary> /// If "n" is defined VECTO uses that instead of the calculated engine speed value. /// </summary> - public PerSecond EngineSpeed { get; set; } + public PerSecond AngularVelocity { get; set; } /// <summary> /// [-] Gear input. Overwrites the gear shift model. /// </summary> - public double Gear { get; set; } + public uint Gear { get; set; } /// <summary> /// This power input will be directly added to the engine power in addition to possible other auxiliaries. Also used in Engine Only Mode. @@ -129,7 +129,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data /// <summary> /// Effective engine torque at clutch. Only required in Engine Only Mode. Alternatively power "Pe" can be defined. Use "DRAG" to define motoring operation. /// </summary> - public NewtonMeter EngineTorque { get; set; } + public NewtonMeter Torque { get; set; } public bool Drag { get; set; } diff --git a/VectoCore/Models/SimulationComponent/Impl/ManualGearbox.cs b/VectoCore/Models/SimulationComponent/Impl/ManualGearbox.cs index ba8cd40fab04c608901d11ddfe2a045e665867cf..c5a87ad65d3b72722fcc625cf46e1b5241233576 100644 --- a/VectoCore/Models/SimulationComponent/Impl/ManualGearbox.cs +++ b/VectoCore/Models/SimulationComponent/Impl/ManualGearbox.cs @@ -14,57 +14,80 @@ * limitations under the Licence. */ +using System; +using System.Diagnostics; using TUGraz.VectoCore.Configuration; using TUGraz.VectoCore.Models.Connector.Ports; using TUGraz.VectoCore.Models.Connector.Ports.Impl; using TUGraz.VectoCore.Models.Simulation; using TUGraz.VectoCore.Models.Simulation.Data; +using TUGraz.VectoCore.Models.Simulation.DataBus; using TUGraz.VectoCore.Models.SimulationComponent.Data; using TUGraz.VectoCore.OutputData; using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { - public class ManualGearbox : Gearbox + public class ManualGearbox : VectoSimulationComponent, IGearbox, ITnOutPort, ITnInPort, IClutchInfo { - public ManualGearbox(IVehicleContainer container, GearboxData gearboxData = null) : base(container, gearboxData) {} + private readonly GearboxData _data; + private ITnOutPort NextComponent { get; set; } + private PerSecond PreviousInAngularSpeed { get; set; } + private Watt PowerLossInertia { get; set; } + private Watt PowerLoss { get; set; } - #region ITnOutPort + private Func<uint> GetGear { get; set; } - public override IResponse Initialize(NewtonMeter outTorque, PerSecond outAngularVelocity) + public uint Gear + { + get { return GetGear(); } + } + + public MeterPerSecond StartSpeed + { + get { return _data.StartSpeed; } + } + + public MeterPerSquareSecond StartAcceleration + { + get { return _data.StartAcceleration; } + } + + public FullLoadCurve GearFullLoadCurve + { + get { return Gear == 0 ? null : _data.Gears[Gear].FullLoadCurve; } + } + + public ManualGearbox(IVehicleContainer container, GearboxData gearboxData, Func<uint> getGear) + : base(container) + { + _data = gearboxData; + GetGear = getGear; + } + + public IResponse Initialize(NewtonMeter outTorque, PerSecond outAngularVelocity) { var dt = Constants.SimulationSettings.TargetTimeInterval; - ShiftTime = double.NegativeInfinity.SI<Second>(); PowerLoss = null; - if (Disengaged) { - Gear = DataBus.Gear; - } - - if (Data == null || Data.Gears == null) { + if (_data == null || _data.Gears == null) { var r = NextComponent.Initialize(outTorque, outAngularVelocity); if (r is ResponseSuccess) { PreviousInAngularSpeed = outAngularVelocity; - Disengaged = false; } return r; } - var inAngularVelocity = outAngularVelocity * Data.Gears[Gear].Ratio; - var inTorque = Data.Gears[Gear].LossMap.GetInTorque(inAngularVelocity, outTorque); + var inAngularVelocity = outAngularVelocity * _data.Gears[Gear].Ratio; + var inTorque = _data.Gears[Gear].LossMap.GetInTorque(inAngularVelocity, outTorque); var torqueLossInertia = outAngularVelocity.IsEqual(0) ? 0.SI<NewtonMeter>() - : Formulas.InertiaPower(inAngularVelocity, PreviousInAngularSpeed, Data.Inertia, dt) / inAngularVelocity; + : Formulas.InertiaPower(inAngularVelocity, PreviousInAngularSpeed, _data.Inertia, dt) / inAngularVelocity; inTorque += torqueLossInertia; var response = NextComponent.Initialize(inTorque, inAngularVelocity); - if (response is ResponseSuccess) { - PreviousInAngularSpeed = inAngularVelocity; - Disengaged = false; - } - return response; } @@ -78,80 +101,30 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl /// <item><description>ResponseGearshift</description></item> /// </list> /// </returns> - public override IResponse Request(Second absTime, Second dt, NewtonMeter torque, PerSecond angularVelocity, + public IResponse Request(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, bool dryRun) { - Log.Debug("Gearbox Power Request: torque: {0}, angularVelocity: {1}", torque, angularVelocity); - IResponse retVal; - if (ClutchClosed(absTime)) { - retVal = RequestGearEngaged(absTime, dt, torque, angularVelocity, dryRun); - } else { - retVal = RequestGearDisengaged(absTime, dt, torque, angularVelocity, dryRun); - } - - return retVal; - } - + Log.Debug("Gearbox Power Request: torque: {0}, angularVelocity: {1}", outTorque, outAngularVelocity); - /// <summary> - /// Requests the gearbox in engaged mode. Sets the gear if no gear was set previously. - /// </summary> - /// <returns> - /// <list type="bullet"> - /// <item><term>ResponseGearShift</term><description>if a shift is needed.</description></item> - /// <item><term>else</term><description>Response from NextComponent.</description></item> - /// </list> - /// </returns> - protected override IResponse RequestGearEngaged(Second absTime, Second dt, NewtonMeter outTorque, - PerSecond outAngularVelocity, - bool dryRun) - { - // Set a Gear if no gear was set and engineSpeed is not zero - if (Disengaged && !outAngularVelocity.IsEqual(0)) { - Disengaged = false; - Gear = DataBus.Gear; - Log.Debug("Gearbox engaged gear {0}", Gear); + if (Gear == 0) { + var disengagedResponse = NextComponent.Request(absTime, dt, 0.SI<NewtonMeter>(), null); + disengagedResponse.GearboxPowerRequest = outTorque * outAngularVelocity; + PreviousInAngularSpeed = DataBus.EngineIdleSpeed; + return disengagedResponse; } - if (Data == null || Data.Gears == null) { - var r = NextComponent.Request(absTime, dt, outTorque, outAngularVelocity); - r.GearboxPowerRequest = outTorque * outAngularVelocity; - - PreviousInAngularSpeed = outAngularVelocity; - return r; - } - var inEngineSpeed = outAngularVelocity * Data.Gears[Gear].Ratio; - var inTorque = outAngularVelocity.IsEqual(0) - ? outTorque / Data.Gears[Gear].Ratio - : Data.Gears[Gear].LossMap.GetInTorque(inEngineSpeed, outTorque); + var inEngineSpeed = outAngularVelocity * _data.Gears[Gear].Ratio; + var inTorque = _data.Gears[Gear].LossMap.GetInTorque(inEngineSpeed, outTorque); PowerLoss = inTorque * inEngineSpeed - outTorque * outAngularVelocity; if (!inEngineSpeed.IsEqual(0)) { - PowerLossInertia = Formulas.InertiaPower(inEngineSpeed, PreviousInAngularSpeed, Data.Inertia, dt); + PowerLossInertia = Formulas.InertiaPower(inEngineSpeed, PreviousInAngularSpeed, _data.Inertia, dt); inTorque += PowerLossInertia / inEngineSpeed; } else { PowerLossInertia = 0.SI<Watt>(); } - var shiftRequired = Gear != DataBus.Gear; - - if (shiftRequired) { - 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, outAngularVelocity, inTorque, inEngineSpeed); - - Disengaged = true; - Log.Info("Gearbox disengaged"); - - return new ResponseGearShift { - Source = this, - SimulationInterval = Data.TractionInterruption, - GearboxPowerRequest = outTorque * outAngularVelocity - }; - } - var response = NextComponent.Request(absTime, dt, inTorque, inEngineSpeed); response.GearboxPowerRequest = outTorque * outAngularVelocity; @@ -159,8 +132,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return response; } - #endregion - protected override void DoWriteModalResults(IModalDataContainer container) { container[ModalResultField.Gear] = Gear; @@ -168,11 +139,37 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl container[ModalResultField.PaGB] = PowerLossInertia; } + protected override void DoCommitSimulationStep() { - if (Data != null && Data.Gears != null) { - base.DoCommitSimulationStep(); + if (_data.Gears[Gear].LossMap.Extrapolated) { + Log.Warn("Gear {0} LossMap data was extrapolated: range for loss map is not sufficient.", Gear); } + + PowerLoss = null; + PowerLossInertia = null; + } + + [DebuggerHidden] + public ITnInPort InPort() + { + return this; + } + + [DebuggerHidden] + public ITnOutPort OutPort() + { + return this; + } + + void ITnInPort.Connect(ITnOutPort other) + { + NextComponent = other; + } + + public bool ClutchClosed(Second absTime) + { + return true; } } } \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/Impl/PowertrainDrivingCycle.cs b/VectoCore/Models/SimulationComponent/Impl/PowertrainDrivingCycle.cs index e1dfeff2de77034cd48c1a22404cdea9ac86a52c..5eaef5b111e867cb43825ca083e97b8b2c35bf0c 100644 --- a/VectoCore/Models/SimulationComponent/Impl/PowertrainDrivingCycle.cs +++ b/VectoCore/Models/SimulationComponent/Impl/PowertrainDrivingCycle.cs @@ -21,7 +21,9 @@ using TUGraz.VectoCore.Exceptions; using TUGraz.VectoCore.Models.Connector.Ports; using TUGraz.VectoCore.Models.Connector.Ports.Impl; using TUGraz.VectoCore.Models.Simulation; +using TUGraz.VectoCore.Models.Simulation.Impl; using TUGraz.VectoCore.Models.SimulationComponent.Data; +using TUGraz.VectoCore.Models.SimulationComponent.Data.Gearbox; using TUGraz.VectoCore.OutputData; using TUGraz.VectoCore.Utils; @@ -84,13 +86,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return new ResponseCycleFinished(); } AbsTime = absTime; - return NextComponent.Request(absTime, dt, Data.Entries[index].EngineTorque, Data.Entries[index].EngineSpeed); + return NextComponent.Request(absTime, dt, Data.Entries[index].Torque, Data.Entries[index].AngularVelocity); } public IResponse Initialize() { var index = 0; - return NextComponent.Initialize(Data.Entries[index].EngineTorque, Data.Entries[index].EngineSpeed); + return NextComponent.Initialize(Data.Entries[index].Torque, Data.Entries[index].AngularVelocity); } public string CycleName @@ -142,4 +144,17 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl }; } } + + public class PWheelCycle : PowertrainDrivingCycle + { + public PWheelCycle(IVehicleContainer container, DrivingCycleData cycle, double axleRatio, + IDictionary<uint, double> gears) : base(container, cycle) + { + gears[0] = 1; + foreach (var entry in Data.Entries) { + entry.AngularVelocity *= axleRatio * gears[entry.Gear]; + entry.Torque = entry.PWheel / entry.AngularVelocity; + } + } + } } \ No newline at end of file diff --git a/VectoCoreTest/Integration/EngineOnlyCycle/EngineOnlyCycleTest.cs b/VectoCoreTest/Integration/EngineOnlyCycle/EngineOnlyCycleTest.cs index 8e35bfbaa58a3bd706ba27b5de381416956d4c97..777e3885b100d88223efa249ad09cc74a48d4246 100644 --- a/VectoCoreTest/Integration/EngineOnlyCycle/EngineOnlyCycleTest.cs +++ b/VectoCoreTest/Integration/EngineOnlyCycle/EngineOnlyCycleTest.cs @@ -64,7 +64,7 @@ namespace TUGraz.VectoCore.Tests.Integration.EngineOnlyCycle var modData = new ModalDataContainer(modFile, fileWriter, ExecutionMode.EngineOnly); foreach (var cycleEntry in data.Entries) { - var response = port.Request(absTime, dt, cycleEntry.EngineTorque, cycleEntry.EngineSpeed); + var response = port.Request(absTime, dt, cycleEntry.Torque, cycleEntry.AngularVelocity); Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); foreach (var sc in vehicle.SimulationComponents()) { modData[ModalResultField.time] = absTime + dt / 2;