diff --git a/VectoCore/Exceptions/VectoSimulationException.cs b/VectoCore/Exceptions/VectoSimulationException.cs index b6f9dd03b9e9bace19ca51bba5bb3c3f51741999..563d56addc1f611dbf6b0fdd1d485d943d60a0de 100644 --- a/VectoCore/Exceptions/VectoSimulationException.cs +++ b/VectoCore/Exceptions/VectoSimulationException.cs @@ -2,7 +2,7 @@ namespace TUGraz.VectoCore.Exceptions { - public class VectoSimulationException : Exception + public class VectoSimulationException : VectoException { public VectoSimulationException(string msg) : base(msg) { } diff --git a/VectoCore/Models/Connector/Ports/IDriverDemandOutPort.cs b/VectoCore/Models/Connector/Ports/IDriverDemandOutPort.cs index 37d8ffe0c584dab1d6ca1996fb6e3dce15832c70..33d69149dee2e4360cc3f746c5331c16b1d958e9 100644 --- a/VectoCore/Models/Connector/Ports/IDriverDemandOutPort.cs +++ b/VectoCore/Models/Connector/Ports/IDriverDemandOutPort.cs @@ -1,10 +1,11 @@ using System; +using TUGraz.VectoCore.Models.Connector.Ports.Impl; using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.Connector.Ports { public interface IDriverDemandOutPort { - void Request(TimeSpan absTime, TimeSpan dt, MeterPerSecond velocity, double gradient); + IResponse Request(TimeSpan absTime, TimeSpan dt, MeterPerSecond velocity, double gradient); } } diff --git a/VectoCore/Models/Connector/Ports/IResponse.cs b/VectoCore/Models/Connector/Ports/IResponse.cs new file mode 100644 index 0000000000000000000000000000000000000000..01ce67de3abca5a82dbb0ac4394d8cddf3de82b1 --- /dev/null +++ b/VectoCore/Models/Connector/Ports/IResponse.cs @@ -0,0 +1,6 @@ +namespace TUGraz.VectoCore.Models.Connector.Ports +{ + public interface IResponse + { + } +} \ No newline at end of file diff --git a/VectoCore/Models/Connector/Ports/ITnOutPort.cs b/VectoCore/Models/Connector/Ports/ITnOutPort.cs index 5e9c68fee833056850e2663bd6a7e19c6edded4c..4f1f342c9e8176df0fac35f80bc878ff8a897bce 100644 --- a/VectoCore/Models/Connector/Ports/ITnOutPort.cs +++ b/VectoCore/Models/Connector/Ports/ITnOutPort.cs @@ -1,4 +1,5 @@ using System; +using TUGraz.VectoCore.Models.Connector.Ports.Impl; using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.Connector.Ports @@ -12,6 +13,6 @@ namespace TUGraz.VectoCore.Models.Connector.Ports /// <param name="dt">[s]</param> /// <param name="torque">[Nm]</param> /// <param name="angularVelocity">[rad/s]</param> - void Request(TimeSpan absTime, TimeSpan dt, NewtonMeter torque, RadianPerSecond angularVelocity); + IResponse Request(TimeSpan absTime, TimeSpan dt, NewtonMeter torque, RadianPerSecond angularVelocity); } } \ No newline at end of file diff --git a/VectoCore/Models/Connector/Ports/Impl/Response.cs b/VectoCore/Models/Connector/Ports/Impl/Response.cs new file mode 100644 index 0000000000000000000000000000000000000000..c49469e3a433a5332e6d7d13541d179367faf039 --- /dev/null +++ b/VectoCore/Models/Connector/Ports/Impl/Response.cs @@ -0,0 +1,22 @@ +using System; + +namespace TUGraz.VectoCore.Models.Connector.Ports.Impl +{ + public class ResponseCycleFinished : IResponse + { + + } + + public class ResponseSuccess : IResponse + { + } + + public class ResponseFailOverload : IResponse + { + } + + public class ResponseFailTimeInterval : IResponse + { + public TimeSpan DeltaT { get; set; } + } +} \ No newline at end of file diff --git a/VectoCore/Models/Simulation/IVectoJob.cs b/VectoCore/Models/Simulation/IVectoJob.cs deleted file mode 100644 index 57b45c519d302d025972c0bf532dda84e985c77d..0000000000000000000000000000000000000000 --- a/VectoCore/Models/Simulation/IVectoJob.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace TUGraz.VectoCore.Models.Simulation -{ - public interface IVectoJob - { - void Run(); - - IVehicleContainer GetContainer(); - } -} \ No newline at end of file diff --git a/VectoCore/Models/Simulation/IVectoSimulator.cs b/VectoCore/Models/Simulation/IVectoSimulator.cs index c07fb0bfc73a2bba321431681d4ec565b86e27a8..e4c46f9e681001fdbfdb6cf1335584f78e65f52b 100644 --- a/VectoCore/Models/Simulation/IVectoSimulator.cs +++ b/VectoCore/Models/Simulation/IVectoSimulator.cs @@ -1,6 +1,11 @@ +using TUGraz.VectoCore.Models.Simulation.Impl; + namespace TUGraz.VectoCore.Models.Simulation { public interface IVectoSimulator { + void Run(); + + IVehicleContainer GetContainer(); } } \ No newline at end of file diff --git a/VectoCore/Models/Simulation/IVehicleContainer.cs b/VectoCore/Models/Simulation/IVehicleContainer.cs index 9d0e5834648f65032e93c01ab472a7128a8c98fd..d242729e24a8c63c97ab3c133c725c0285d7e2bd 100644 --- a/VectoCore/Models/Simulation/IVehicleContainer.cs +++ b/VectoCore/Models/Simulation/IVehicleContainer.cs @@ -4,10 +4,10 @@ using TUGraz.VectoCore.Models.SimulationComponent; namespace TUGraz.VectoCore.Models.Simulation { - public interface IVehicleContainer : ICockpit - { - void AddComponent(VectoSimulationComponent component); - void CommitSimulationStep(IModalDataWriter dataWriter); - void FinishSimulation(IModalDataWriter dataWriter); - } + public interface IVehicleContainer : ICockpit + { + void AddComponent(VectoSimulationComponent component); + void CommitSimulationStep(IModalDataWriter dataWriter); + void FinishSimulation(IModalDataWriter dataWriter); + } } \ No newline at end of file diff --git a/VectoCore/Models/Simulation/Impl/JobContainer.cs b/VectoCore/Models/Simulation/Impl/JobContainer.cs new file mode 100644 index 0000000000000000000000000000000000000000..bf0e750d3539dc9fdd78c4897ebfb7ed38287623 --- /dev/null +++ b/VectoCore/Models/Simulation/Impl/JobContainer.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Common.Logging; + +namespace TUGraz.VectoCore.Models.Simulation.Impl +{ + //todo: add job tracking (state of jobs, iteration, ...) + //todo: add job control (pause, stop) + public class JobContainer + { + private List<IVectoSimulator> _simulators = new List<IVectoSimulator>(); + + public void AddJob(IVectoSimulator sim) + { + _simulators.Add(sim); + } + + public void RunSimulation() + { + LogManager.GetLogger(GetType()).Info("VectoSimulator started running. Starting Jobs."); + Task.WaitAll(_simulators.Select(job => Task.Factory.StartNew(job.Run)).ToArray()); + } + } +} \ No newline at end of file diff --git a/VectoCore/Models/Simulation/Impl/SimulationFactory.cs b/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs similarity index 53% rename from VectoCore/Models/Simulation/Impl/SimulationFactory.cs rename to VectoCore/Models/Simulation/Impl/SimulatorFactory.cs index bc3dcb72245a4b036ce9cec14e74373785f5153c..20b0ae4f2ea00b88f4eee227c22beeb803112bed 100644 --- a/VectoCore/Models/Simulation/Impl/SimulationFactory.cs +++ b/VectoCore/Models/Simulation/Impl/SimulatorFactory.cs @@ -6,38 +6,38 @@ using TUGraz.VectoCore.Models.SimulationComponent.Impl; namespace TUGraz.VectoCore.Models.Simulation.Impl { - public class SimulationFactory + public class SimulatorFactory { - public static IVectoJob CreateTimeBasedEngineOnlyJob(string engineFile, string cycleFile, string resultFile) + public static IVectoSimulator CreateTimeBasedEngineOnlyJob(string engineFile, string cycleFile, string resultFile) { - Action<string> debug = LogManager.GetLogger<SimulationFactory>().Debug; + Action<string> debug = LogManager.GetLogger<SimulatorFactory>().Debug; - debug("SimulationFactory creating VehicleContainer."); + debug("Creating VehicleContainer."); var container = new VehicleContainer(); - debug("SimulationFactory creating engine."); + debug("Creating engine."); var engineData = CombustionEngineData.ReadFromFile(engineFile); var engine = new CombustionEngine(container, engineData); - debug("SimulationFactory creating gearbox."); + debug("Creating gearbox."); var gearBox = new EngineOnlyGearbox(container); - debug("SimulationFactory creating cycle."); + debug("Creating cycle."); var cycleData = DrivingCycleData.ReadFromFileEngineOnly(cycleFile); var cycle = new EngineOnlyDrivingCycle(container, cycleData); - debug("SimulationFactory connecting gearbox with engine."); + debug("Connecting gearbox with engine."); gearBox.InShaft().Connect(engine.OutShaft()); - debug("SimulationFactory connecting cycle with gearbox."); + debug("Connecting cycle with gearbox."); cycle.InShaft().Connect(gearBox.OutShaft()); var dataWriter = new ModalDataWriter(resultFile); - debug("SimulationFactory creating VectoJob."); - var job = new VectoJob(container, cycle, dataWriter); + debug("Creating Simulator."); + var simulator = new VectoSimulator(container, cycle, dataWriter); - return job; + return simulator; } } } \ No newline at end of file diff --git a/VectoCore/Models/Simulation/Impl/VectoJob.cs b/VectoCore/Models/Simulation/Impl/VectoJob.cs deleted file mode 100644 index 6d40f31879a77932ba99cb8a23a18d3c31921684..0000000000000000000000000000000000000000 --- a/VectoCore/Models/Simulation/Impl/VectoJob.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Common.Logging; -using TUGraz.VectoCore.Models.Simulation.Data; -using TUGraz.VectoCore.Models.SimulationComponent; - -namespace TUGraz.VectoCore.Models.Simulation.Impl -{ - public class VectoJob : IVectoJob - { - protected IEngineOnlyDrivingCycle Cycle { get; set; } - protected IModalDataWriter DataWriter { get; set; } - protected IVehicleContainer Container { get; set; } - - public IVehicleContainer GetContainer() - { - return Container; - } - - public VectoJob(IVehicleContainer container, IEngineOnlyDrivingCycle cycle, IModalDataWriter dataWriter) - { - Container = container; - Cycle = cycle; - DataWriter = dataWriter; - } - - public void Run() - { - LogManager.GetLogger(GetType()).Info("VectoJob started running."); - while (Cycle.DoSimulationStep()) - { - Container.CommitSimulationStep(DataWriter); - } - Container.FinishSimulation(DataWriter); - LogManager.GetLogger(GetType()).Info("VectoJob finished."); - } - } -} \ No newline at end of file diff --git a/VectoCore/Models/Simulation/Impl/VectoSimulator.cs b/VectoCore/Models/Simulation/Impl/VectoSimulator.cs index d628cfdb8359be70e0dbcd4ce36d7cbd4b3b4a6d..d3749b35799cfb6f3caafabc8c208db5dfc8ea16 100644 --- a/VectoCore/Models/Simulation/Impl/VectoSimulator.cs +++ b/VectoCore/Models/Simulation/Impl/VectoSimulator.cs @@ -1,25 +1,66 @@ -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +using System; using Common.Logging; +using TUGraz.VectoCore.Exceptions; +using TUGraz.VectoCore.Models.Connector.Ports; +using TUGraz.VectoCore.Models.Connector.Ports.Impl; +using TUGraz.VectoCore.Models.Simulation.Data; +using TUGraz.VectoCore.Models.SimulationComponent; namespace TUGraz.VectoCore.Models.Simulation.Impl { - //todo: add job tracking (state of jobs, iteration, ...) - //todo: add job control (pause, stop) public class VectoSimulator : IVectoSimulator { - private List<IVectoJob> _jobs = new List<IVectoJob>(); + private TimeSpan _absTime = new TimeSpan(seconds: 0, minutes: 0, hours: 0); + private TimeSpan _dt = new TimeSpan(seconds: 1, minutes: 0, hours: 0); - public void AddJob(IVectoJob job) + protected IDrivingCycle Cycle { get; set; } + protected IModalDataWriter DataWriter { get; set; } + protected IVehicleContainer Container { get; set; } + + public IVehicleContainer GetContainer() + { + return Container; + } + + public VectoSimulator(IVehicleContainer container, IDrivingCycle cycle, IModalDataWriter dataWriter) { - _jobs.Add(job); + Container = container; + Cycle = cycle; + DataWriter = dataWriter; } - public void RunSimulation() + public void Run() { - LogManager.GetLogger(GetType()).Info("VectoSimulator started running. Starting Jobs."); - Task.WaitAll(_jobs.Select(job => Task.Factory.StartNew(job.Run)).ToArray()); + LogManager.GetLogger(GetType()).Info("VectoJob started running."); + IResponse response; + do + { + response = Cycle.Request(_absTime, _dt); + while (response is ResponseFailTimeInterval) + { + _dt = (response as ResponseFailTimeInterval).DeltaT; + response = Cycle.Request(_absTime, _dt); + } + + if (response is ResponseCycleFinished) + break; + + _absTime += _dt; + + DataWriter[ModalResultField.time] = (_absTime - TimeSpan.FromTicks(_dt.Ticks / 2)).TotalSeconds; + DataWriter[ModalResultField.simulationInterval] = _dt.TotalSeconds; + + Container.CommitSimulationStep(DataWriter); + + // set _dt to difference to next full second. + _dt = TimeSpan.FromSeconds(1) - TimeSpan.FromMilliseconds(_dt.Milliseconds); + } while (response is ResponseSuccess); + + Container.FinishSimulation(DataWriter); + + //todo: write vsum file + + LogManager.GetLogger(GetType()).Info("VectoJob finished."); } } } \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/Data/DrivingCycleData.cs b/VectoCore/Models/SimulationComponent/Data/DrivingCycleData.cs index 0a7fe2db96852e3543735f383cb0fd34092412e8..f18ea3662eec0b1f6fba0ae95e400bc2a5a8c79b 100644 --- a/VectoCore/Models/SimulationComponent/Data/DrivingCycleData.cs +++ b/VectoCore/Models/SimulationComponent/Data/DrivingCycleData.cs @@ -312,9 +312,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data { ValidateHeader(table.Columns.Cast<DataColumn>().Select(col => col.ColumnName).ToArray()); - var entries = table.Rows.Cast<DataRow>().Select(row => new DrivingCycleEntry + var entries = table.Rows.Cast<DataRow>().Select((row, index) => new DrivingCycleEntry { - Time = row.ParseDoubleOrGetDefault(Fields.Time), + Time = row.ParseDoubleOrGetDefault(Fields.Time, index), VehicleSpeed = row.ParseDouble(Fields.VehicleSpeed).SI().Kilo.Meter.Per.Hour.To<MeterPerSecond>(), RoadGradient = row.ParseDoubleOrGetDefault(Fields.RoadGradient), AdditionalAuxPowerDemand = row.ParseDoubleOrGetDefault(Fields.AdditionalAuxPowerDemand).SI().Kilo.Watt.To<Watt>(), @@ -325,13 +325,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Data AuxiliarySupplyPower = AuxSupplyPowerReader.Read(row) }).ToArray(); - // update time with 1Hz if time field is missing. - if (!table.Columns.Contains(Fields.Time)) - { - for (var i = 0; i < entries.Length; i++) - entries[i].Time = i; - } - return entries; } } diff --git a/VectoCore/Models/SimulationComponent/IDrivingCycle.cs b/VectoCore/Models/SimulationComponent/IDrivingCycle.cs index ecc03f797b27825a22bd3af578c0acefea01c046..1aea420080c701d96f6aebcc1a6c700e999f856e 100644 --- a/VectoCore/Models/SimulationComponent/IDrivingCycle.cs +++ b/VectoCore/Models/SimulationComponent/IDrivingCycle.cs @@ -1,14 +1,21 @@ +using System; using TUGraz.VectoCore.Models.Connector.Ports; +using TUGraz.VectoCore.Models.Connector.Ports.Impl; namespace TUGraz.VectoCore.Models.SimulationComponent { - public interface IDrivingCycle : IDriverDemandInProvider + public interface IDrivingCycle { - bool DoSimulationStep(); + IResponse Request(TimeSpan absTime, TimeSpan dt); } - public interface IEngineOnlyDrivingCycle: IInShaft + public interface IDriverDemandDrivingCycle : IDrivingCycle, IDriverDemandInProvider { - bool DoSimulationStep(); + + } + + public interface IEngineOnlyDrivingCycle : IDrivingCycle, IInShaft + { + } } \ No newline at end of file diff --git a/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs b/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs index f90d7953c86e92ed7aa3b0713f2c32374a916fee..9e715ad0137a04be2b71db7af044f26bb0cb54c4 100644 --- a/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs +++ b/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics.Contracts; 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.Data; using TUGraz.VectoCore.Models.SimulationComponent.Data; @@ -190,7 +191,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl _currentState = new EngineState(); } - public void Request(TimeSpan absTime, TimeSpan dt, NewtonMeter torque, RadianPerSecond engineSpeed) + public IResponse Request(TimeSpan absTime, TimeSpan dt, NewtonMeter torque, RadianPerSecond engineSpeed) { _currentState.EngineSpeed = engineSpeed; _currentState.AbsTime = absTime; @@ -221,6 +222,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl _currentState.EnginePower = requestedEnginePower; //todo + _currentState.EnginePowerLoss; _currentState.EngineTorque = Formulas.PowerToTorque(_currentState.EnginePower, _currentState.EngineSpeed); + + //todo: use ResponseOverloadFail in case of overload + return new ResponseSuccess(); } /// <summary> diff --git a/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs b/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs deleted file mode 100644 index 7254988456a138d4ad8ee519c6ba9956ee37c04e..0000000000000000000000000000000000000000 --- a/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using TUGraz.VectoCore.Models.Connector.Ports; -using TUGraz.VectoCore.Models.Simulation; -using TUGraz.VectoCore.Models.Simulation.Data; -using TUGraz.VectoCore.Models.SimulationComponent.Data; - -namespace TUGraz.VectoCore.Models.SimulationComponent.Impl -{ - /// <summary> - /// Class representing one Distance Based Driving Cycle - /// </summary> - public class DistanceBasedDrivingCycle : VectoSimulationComponent, IDrivingCycle, IDriverDemandInPort - { - protected TimeSpan AbsTime = new TimeSpan(seconds: 0, minutes: 0, hours: 0); - protected TimeSpan Dt = new TimeSpan(seconds: 1, minutes: 0, hours: 0); - protected double Distance = 0; - - protected DrivingCycleData Data; - - private IDriverDemandOutPort OutPort { get; set; } - - private int CurrentStep { get; set; } - - public DistanceBasedDrivingCycle(IVehicleContainer container, DrivingCycleData cycle) - { - Data = cycle; - container.AddComponent(this); - } - - #region IDrivingCycle - public bool DoSimulationStep() - { - //todo: Distance calculation and comparison!!! - throw new NotImplementedException("Distance based Cycle is not yet implemented."); - } - #endregion - - public override void CommitSimulationStep(IModalDataWriter writer) - { - // AbsTime gets increased before doing the CommitSimulationStep, - // therefore it has to be decreased again for commit. The needed time - // for the moddata is between the last AbsTime and the current AbsTime, - // therefore dt/2 has to be subtracted from the current AbsTime. - // todo: document this in a jira ticket! - var halfDt = new TimeSpan(Dt.Ticks / 2); - writer[ModalResultField.time] = (AbsTime - halfDt).TotalSeconds; - } - - public IDriverDemandInPort InPort() - { - return this; - } - - public void Connect(IDriverDemandOutPort other) - { - OutPort = other; - } - } -} diff --git a/VectoCore/Models/SimulationComponent/Impl/EngineOnlyDrivingCycle.cs b/VectoCore/Models/SimulationComponent/Impl/EngineOnlyDrivingCycle.cs index acf7411e533436f99f26136b45814aac6e4606b5..02bb3e9cc277d39de143017b5f19fa0ac39b4e2f 100644 --- a/VectoCore/Models/SimulationComponent/Impl/EngineOnlyDrivingCycle.cs +++ b/VectoCore/Models/SimulationComponent/Impl/EngineOnlyDrivingCycle.cs @@ -1,5 +1,6 @@ using System; 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.SimulationComponent.Data; @@ -11,39 +12,17 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl /// </summary> public class EngineOnlyDrivingCycle : VectoSimulationComponent, IEngineOnlyDrivingCycle, ITnInPort { - protected TimeSpan AbsTime = new TimeSpan(seconds: 0, minutes: 0, hours: 0); - protected TimeSpan dt = new TimeSpan(seconds: 1, minutes: 0, hours: 0); protected DrivingCycleData Data; private ITnOutPort OutPort { get; set; } - private int CurrentStep { get; set; } - public EngineOnlyDrivingCycle(IVehicleContainer container, DrivingCycleData cycle) { Data = cycle; container.AddComponent(this); } - #region IDrivingCycle - public bool DoSimulationStep() - { - if (CurrentStep >= Data.Entries.Count) - return false; - - var entry = Data.Entries[CurrentStep]; - - //todo: variable time steps! - dt = TimeSpan.FromSeconds(1); - - OutPort.Request(AbsTime, dt, entry.EngineTorque, entry.EngineSpeed); - AbsTime += dt; - CurrentStep++; - return true; - } - #endregion - #region ITnInPort public void Connect(ITnOutPort other) { @@ -56,18 +35,22 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { return this; } + + public IResponse Request(TimeSpan absTime, TimeSpan dt) + { + //todo: change to variable time steps + var index = (int)Math.Floor(absTime.TotalSeconds); + if (index >= Data.Entries.Count) + return new ResponseCycleFinished(); + + return OutPort.Request(absTime, dt, Data.Entries[index].EngineTorque, Data.Entries[index].EngineSpeed); + } + #endregion public override void CommitSimulationStep(IModalDataWriter writer) { - // AbsTime gets increased before doing the CommitSimulationStep, - // therefore it has to be decreased again for commit. The needed time - // for the moddata is between the last AbsTime and the current AbsTime, - // therefore dt/2 has to be subtracted from the current AbsTime. - // todo: document dt/2 in a jira ticket! - writer[ModalResultField.time] = (AbsTime - TimeSpan.FromTicks(dt.Ticks / 2)).TotalSeconds; - writer[ModalResultField.simulationInterval] = dt.TotalSeconds; - } + } } diff --git a/VectoCore/Models/SimulationComponent/Impl/EngineOnlyGearbox.cs b/VectoCore/Models/SimulationComponent/Impl/EngineOnlyGearbox.cs index 1f8ebb23d4323117cdf8eef1acc3f3fda90c8074..0c2ba62e4eb58659e2f9a7753a3db2493789de39 100644 --- a/VectoCore/Models/SimulationComponent/Impl/EngineOnlyGearbox.cs +++ b/VectoCore/Models/SimulationComponent/Impl/EngineOnlyGearbox.cs @@ -1,5 +1,6 @@ using System; 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.Utils; @@ -27,9 +28,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return 0; } - public void Request(TimeSpan absTime, TimeSpan dt, NewtonMeter torque, RadianPerSecond engineSpeed) + public IResponse Request(TimeSpan absTime, TimeSpan dt, NewtonMeter torque, RadianPerSecond engineSpeed) { - _outPort.Request(absTime, dt, torque, engineSpeed); + return _outPort.Request(absTime, dt, torque, engineSpeed); } public void Connect(ITnOutPort other) diff --git a/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs b/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs index 531e9d8725f2c9847365aa9c5fc22e5ef037043d..a0d70a673309992d1905b8db3e67948ee835c16a 100644 --- a/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs +++ b/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs @@ -1,5 +1,6 @@ using System; 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.Utils; @@ -26,7 +27,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl throw new NotImplementedException(); } - public void Request(TimeSpan absTime, TimeSpan dt, NewtonMeter torque, RadianPerSecond engineSpeed) + public IResponse Request(TimeSpan absTime, TimeSpan dt, NewtonMeter torque, RadianPerSecond engineSpeed) { throw new NotImplementedException(); } diff --git a/VectoCore/Models/SimulationComponent/Impl/TimeBasedDrivingCycle.cs b/VectoCore/Models/SimulationComponent/Impl/TimeBasedDrivingCycle.cs index 77f0de09fd09a4990832b4f38c22f964add5678e..2a67229a2642181ca4c5b36cbc8804c780d34fb7 100644 --- a/VectoCore/Models/SimulationComponent/Impl/TimeBasedDrivingCycle.cs +++ b/VectoCore/Models/SimulationComponent/Impl/TimeBasedDrivingCycle.cs @@ -1,58 +1,40 @@ using System; +using System.CodeDom; +using System.Collections.Generic; +using System.Linq; 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.SimulationComponent.Data; +using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { /// <summary> /// Class representing one Time Based Driving Cycle /// </summary> - public class TimeBasedDrivingCycle : VectoSimulationComponent, IDrivingCycle, IDriverDemandInPort + public class TimeBasedDrivingCycle : VectoSimulationComponent, IDriverDemandDrivingCycle, IDriverDemandInPort { - protected TimeSpan AbsTime; - protected TimeSpan dt = TimeSpan.FromSeconds(1); - protected DrivingCycleData Data; private IDriverDemandOutPort OutPort { get; set; } - private int CurrentStep { get; set; } - public TimeBasedDrivingCycle(IVehicleContainer container, DrivingCycleData cycle) { Data = cycle; + _nextIterator = Data.Entries.AsEnumerable().GetEnumerator(); + _current = _nextIterator.Current; container.AddComponent(this); } - #region IDrivingCycle - public bool DoSimulationStep() - { - if (CurrentStep >= Data.Entries.Count) - return false; + private DrivingCycleData.DrivingCycleEntry _current; - var entry = Data.Entries[CurrentStep]; + private readonly IEnumerator<DrivingCycleData.DrivingCycleEntry> _nextIterator; - //todo: variable time steps! - dt = TimeSpan.FromSeconds(1); - - OutPort.Request(AbsTime, dt, entry.VehicleSpeed, entry.RoadGradient); - AbsTime += dt; - CurrentStep++; - return true; - } - #endregion public override void CommitSimulationStep(IModalDataWriter writer) { - // AbsTime gets increased before doing the CommitSimulationStep, - // therefore it has to be decreased again for commit. The needed time - // for the moddata is between the last AbsTime and the current AbsTime, - // therefore dt/2 has to be subtracted from the current AbsTime. - // todo: document this in a jira ticket! - var halfDt = new TimeSpan(dt.Ticks / 2); - writer[ModalResultField.time] = (AbsTime - halfDt).TotalSeconds; } public IDriverDemandInPort InPort() @@ -60,6 +42,16 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return this; } + public IResponse Request(TimeSpan absTime, TimeSpan dt) + { + //todo: change to variable time steps + var index = (int)Math.Floor(absTime.TotalSeconds); + if (index >= Data.Entries.Count) + return new ResponseCycleFinished(); + + return OutPort.Request(absTime, dt, Data.Entries[index].VehicleSpeed, Data.Entries[index].RoadGradient); + } + public void Connect(IDriverDemandOutPort other) { OutPort = other; diff --git a/VectoCore/Utils/DataRowExtensionMethods.cs b/VectoCore/Utils/DataRowExtensionMethods.cs index 651f22b8cdd3edefeb3024106615bc5f7aede1f8..82015be236670c3d2fe8a77a7cadd40026c623a4 100644 --- a/VectoCore/Utils/DataRowExtensionMethods.cs +++ b/VectoCore/Utils/DataRowExtensionMethods.cs @@ -10,10 +10,12 @@ namespace TUGraz.VectoCore.Utils public static double ParseDoubleOrGetDefault(this DataRow row, string columnName, double defaultValue = default(double)) { - double result; - if (double.TryParse(row.Field<string>(columnName), NumberStyles.Any, CultureInfo.InvariantCulture, out result)) - return result; - + if (row.Table.Columns.Contains(columnName)) + { + double result; + if (double.TryParse(row.Field<string>(columnName), NumberStyles.Any, CultureInfo.InvariantCulture, out result)) + return result; + } return defaultValue; } diff --git a/VectoCore/Utils/SI.cs b/VectoCore/Utils/SI.cs index a0fe357e4b4fcca35241dff1b16af1c98029271b..79043e5b329abf5c8e830b8117229f081f878383 100644 --- a/VectoCore/Utils/SI.cs +++ b/VectoCore/Utils/SI.cs @@ -28,6 +28,11 @@ namespace TUGraz.VectoCore.Utils public RadianPerSecond(double val = 0) : base(val, new SI().Radian.Per.Second) { } } + public class RoundsPerMinute : SI + { + public RoundsPerMinute(double val = 0) : base(val, new SI().Rounds.Per.Minute) { } + } + public class NewtonMeter : SI { public NewtonMeter(double val = 0) : base(val, new SI().Newton.Meter) { } diff --git a/VectoCore/VectoCore.csproj b/VectoCore/VectoCore.csproj index a26dbfb6c289ef824e055dff5799da0f8bf36f77..784c943f0a938ac2b4f10e57a5a63f1dbf760725 100644 --- a/VectoCore/VectoCore.csproj +++ b/VectoCore/VectoCore.csproj @@ -115,8 +115,10 @@ <Compile Include="Models\Connector\Ports\IDriverDemandOutPort.cs" /> <Compile Include="Models\Connector\Ports\IDriverDemandOutProvider.cs" /> <Compile Include="Models\Connector\Ports\Impl\InPort.cs" /> + <Compile Include="Models\Connector\Ports\IResponse.cs" /> <Compile Include="Models\Connector\Ports\Impl\OutPort.cs" /> <Compile Include="Models\Connector\Ports\IOutShaft.cs" /> + <Compile Include="Models\Connector\Ports\Impl\Response.cs" /> <Compile Include="Models\Connector\Ports\ITnInPort.cs" /> <Compile Include="Models\Connector\Ports\ITnOutPort.cs" /> <Compile Include="Models\Connector\Ports\ITnPort.cs" /> @@ -132,7 +134,6 @@ <Compile Include="Models\Connector\Ports\IInPort.cs" /> <Compile Include="Models\SimulationComponent\IGearbox.cs" /> <Compile Include="Models\SimulationComponent\IDrivingCycle.cs" /> - <Compile Include="Models\SimulationComponent\Impl\DistanceBasedDrivingCycle.cs" /> <Compile Include="Models\SimulationComponent\Impl\TimeBasedDrivingCycle.cs" /> <Compile Include="Utils\IMemento.cs" /> <Compile Include="Models\SimulationComponent\Impl\CombustionEngine.cs" /> @@ -148,12 +149,11 @@ <Compile Include="Models\Simulation\Data\ModalResult.cs"> <SubType>Component</SubType> </Compile> - <Compile Include="Models\Simulation\IVectoJob.cs" /> <Compile Include="Models\Simulation\IVectoSimulator.cs" /> <Compile Include="Models\Simulation\Data\ModalDataWriter.cs" /> - <Compile Include="Models\Simulation\Impl\SimulationFactory.cs" /> - <Compile Include="Models\Simulation\Impl\VectoJob.cs" /> + <Compile Include="Models\Simulation\Impl\SimulatorFactory.cs" /> <Compile Include="Models\Simulation\Impl\VectoSimulator.cs" /> + <Compile Include="Models\Simulation\Impl\JobContainer.cs" /> <Compile Include="Models\Simulation\Impl\VehicleContainer.cs" /> <Compile Include="Models\Simulation\Cockpit\ICockpit.cs" /> <Compile Include="Models\Simulation\Cockpit\IEngineCockpit.cs" /> diff --git a/VectoCoreArchitecture/VectoCoreArchitecture.modelproj b/VectoCoreArchitecture/VectoCoreArchitecture.modelproj index cc909e3aea691b7310f2de50d51147b9aa6d4c19..8d6cf9aa625418497deebf5bdf20ee4756f30628 100644 --- a/VectoCoreArchitecture/VectoCoreArchitecture.modelproj +++ b/VectoCoreArchitecture/VectoCoreArchitecture.modelproj @@ -111,13 +111,6 @@ <SubType>Content</SubType> <DependentUpon>Simulation.sequencediagram</DependentUpon> </Content> - <Content Include="UMLActivityDiagram1.activitydiagram"> - <SubType>Content</SubType> - </Content> - <Content Include="UMLActivityDiagram1.activitydiagram.layout"> - <SubType>Content</SubType> - <DependentUpon>UMLActivityDiagram1.activitydiagram</DependentUpon> - </Content> <Content Include="UMLClassDiagram1.classdiagram"> <SubType>Content</SubType> </Content> diff --git a/VectoCoreTest/Models/Simulation/DrivingCycleTests.cs b/VectoCoreTest/Models/Simulation/DrivingCycleTests.cs index b58ed85f5ee7f15df83db9552a84cda5de841b95..056d1432e3d1c8ebeb7c7a3c8b5408065c2fb7a0 100644 --- a/VectoCoreTest/Models/Simulation/DrivingCycleTests.cs +++ b/VectoCoreTest/Models/Simulation/DrivingCycleTests.cs @@ -1,10 +1,13 @@ using System; using Microsoft.VisualStudio.TestTools.UnitTesting; +using TUGraz.VectoCore.Models.Connector.Ports; +using TUGraz.VectoCore.Models.Connector.Ports.Impl; using TUGraz.VectoCore.Models.Simulation.Impl; using TUGraz.VectoCore.Models.Simulation.Data; using TUGraz.VectoCore.Models.SimulationComponent; using TUGraz.VectoCore.Models.SimulationComponent.Data; using TUGraz.VectoCore.Models.SimulationComponent.Impl; +using TUGraz.VectoCore.Tests.Models.SimulationComponent; using TUGraz.VectoCore.Tests.Utils; using TUGraz.VectoCore.Utils; @@ -19,33 +22,35 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation var container = new VehicleContainer(); var cycleData = DrivingCycleData.ReadFromFileEngineOnly(@"TestData\Cycles\Coach Engine Only.vdri"); - IEngineOnlyDrivingCycle cycle = new EngineOnlyDrivingCycle(container, cycleData); + var cycle = new EngineOnlyDrivingCycle(container, cycleData); var outPort = new MockTnOutPort(); var inPort = cycle.InShaft(); inPort.Connect(outPort); - cycle.DoSimulationStep(); + var absTime = new TimeSpan(); + var dt = TimeSpan.FromSeconds(1); + + var response = cycle.Request(absTime, dt); + Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); var dataWriter = new TestModalDataWriter(); container.CommitSimulationStep(dataWriter); - Assert.AreEqual(0.0, outPort.AbsTime.TotalSeconds); - Assert.AreEqual(1.0, outPort.Dt.TotalSeconds); - Assert.AreEqual(new SI(600).Rounds.Per.Minute, outPort.AngularFrequency); + Assert.AreEqual(absTime, outPort.AbsTime); + Assert.AreEqual(dt, outPort.Dt); + Assert.AreEqual(600.0.RPMtoRad(), outPort.AngularFrequency); Assert.AreEqual(0.SI<NewtonMeter>(), outPort.Torque); - - Assert.AreEqual(0.5, dataWriter[ModalResultField.time]); } [TestMethod] - public void TestTimeBased() + public void Test_TimeBased_FirstCycle() { var container = new VehicleContainer(); var cycleData = DrivingCycleData.ReadFromFileTimeBased(@"TestData\Cycles\Coach time based.vdri"); - IDrivingCycle cycle = new TimeBasedDrivingCycle(container, cycleData); + var cycle = new TimeBasedDrivingCycle(container, cycleData); var outPort = new MockDriverDemandOutPort(); @@ -53,53 +58,25 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation inPort.Connect(outPort); - cycle.DoSimulationStep(); + var absTime = new TimeSpan(); + var dt = TimeSpan.FromSeconds(1); - var dataWriter = new TestModalDataWriter(); - container.CommitSimulationStep(dataWriter); + var response = cycle.Request(absTime, dt); + Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); - // todo: assert correct values! - Assert.AreEqual(0.0, outPort.AbsTime.TotalSeconds); - Assert.AreEqual(1.0, outPort.Dt.TotalSeconds); + Assert.AreEqual(absTime, outPort.AbsTime); + Assert.AreEqual(dt, outPort.Dt); Assert.AreEqual(0.0.SI<MeterPerSecond>(), outPort.Velocity); Assert.AreEqual(-0.020237973, outPort.Gradient); - Assert.AreEqual(0.5, dataWriter[ModalResultField.time]); - } - - [TestMethod] - public void TestDistanceBased() - { - var container = new VehicleContainer(); - - var cycleData = DrivingCycleData.ReadFromFileDistanceBased(@"TestData\Cycles\Coach.vdri"); - IDrivingCycle cycle = new DistanceBasedDrivingCycle(container, cycleData); - - var outPort = new MockDriverDemandOutPort(); - - var inPort = cycle.InPort(); - - inPort.Connect(outPort); - - cycle.DoSimulationStep(); - - var dataWriter = new TestModalDataWriter(); - container.CommitSimulationStep(dataWriter); - - // todo: assert correct values! - Assert.AreEqual(0.0, outPort.AbsTime.TotalSeconds); - Assert.AreEqual(1.0, outPort.Dt.TotalSeconds); - Assert.AreEqual(80, outPort.Velocity); - Assert.AreEqual(0.03, outPort.Gradient); - Assert.AreEqual(0.5, dataWriter[ModalResultField.time]); } [TestMethod] - public void TestTimeBasedTimeFieldMissing() + public void Test_TimeBased_TimeFieldMissing() { var container = new VehicleContainer(); var cycleData = DrivingCycleData.ReadFromFileTimeBased(@"TestData\Cycles\Cycle time field missing.vdri"); - IDrivingCycle cycle = new TimeBasedDrivingCycle(container, cycleData); + var cycle = new TimeBasedDrivingCycle(container, cycleData); var outPort = new MockDriverDemandOutPort(); @@ -110,17 +87,13 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation var dataWriter = new TestModalDataWriter(); var absTime = new TimeSpan(); var dt = TimeSpan.FromSeconds(1); - var time = 0.5; - while (cycle.DoSimulationStep()) + while (cycle.Request(absTime, dt) is ResponseSuccess) { - container.CommitSimulationStep(dataWriter); - Assert.AreEqual(absTime, outPort.AbsTime); Assert.AreEqual(dt, outPort.Dt); - Assert.AreEqual(time, dataWriter[ModalResultField.time]); + container.CommitSimulationStep(dataWriter); - time = time + dt.TotalSeconds; absTime += dt; } } diff --git a/VectoCoreTest/Models/Simulation/SimulationTests.cs b/VectoCoreTest/Models/Simulation/SimulationTests.cs index 5d131c7ed4cd9e5f8859d598a9972ff0f06eb9ba..21370fc7df7f74d7c42f981c27b96f0ce1ac37f0 100644 --- a/VectoCoreTest/Models/Simulation/SimulationTests.cs +++ b/VectoCoreTest/Models/Simulation/SimulationTests.cs @@ -1,7 +1,4 @@ -using System; -using System.Data; -using System.IO; -using System.Linq; +using System.Data; using Microsoft.VisualStudio.TestTools.UnitTesting; using TUGraz.VectoCore.Models.Simulation.Impl; using TUGraz.VectoCore.Exceptions; @@ -19,11 +16,11 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation [TestMethod] public void TestSimulationEngineOnly() { - var job = SimulationFactory.CreateTimeBasedEngineOnlyJob(EngineFile, CycleFile, "TestEngineOnly-result.vmod"); + var job = SimulatorFactory.CreateTimeBasedEngineOnlyJob(EngineFile, CycleFile, "TestEngineOnly-result.vmod"); var container = job.GetContainer(); - Assert.AreEqual(560.SI().Rounds.Per.Minute, container.EngineSpeed()); + Assert.AreEqual(560.0.RPMtoRad(), container.EngineSpeed()); Assert.AreEqual(0U, container.Gear()); try @@ -43,7 +40,7 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation var resultFileName = "TestEngineOnly_JobRun-result.vmod"; var expectedResultsName = @"TestData\Results\EngineOnlyCycles\24tCoach_EngineOnly.vmod"; - var job = SimulationFactory.CreateTimeBasedEngineOnlyJob(EngineFile, CycleFile, resultFileName); + var job = SimulatorFactory.CreateTimeBasedEngineOnlyJob(EngineFile, CycleFile, resultFileName); job.Run(); var results = ModalResults.ReadFromFile(resultFileName); @@ -64,8 +61,8 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation [TestMethod] public void TestEngineOnly_SimulatorRun() { - var sim = new VectoSimulator(); - var job = SimulationFactory.CreateTimeBasedEngineOnlyJob(EngineFile, CycleFile, + var sim = new JobContainer(); + var job = SimulatorFactory.CreateTimeBasedEngineOnlyJob(EngineFile, CycleFile, "TestEngineOnly-SimulatorRun-result.vmod"); sim.AddJob(job); sim.RunSimulation(); @@ -77,21 +74,21 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation [TestMethod] public void TestEngineOnly_MultipleJobs() { - var sim = new VectoSimulator(); + var simulation = new JobContainer(); - var job1 = SimulationFactory.CreateTimeBasedEngineOnlyJob(EngineFile, CycleFile, - "TestEngineOnly-MultipleJobs-result1.vmod"); - sim.AddJob(job1); + var sim1 = SimulatorFactory.CreateTimeBasedEngineOnlyJob(EngineFile, CycleFile, + "TestEngineOnly-MultipleJobs-result1.vmod"); + simulation.AddJob(sim1); - var job2 = SimulationFactory.CreateTimeBasedEngineOnlyJob(EngineFile, CycleFile, - "TestEngineOnly-MultipleJobs-result2.vmod"); - sim.AddJob(job2); + var sim2 = SimulatorFactory.CreateTimeBasedEngineOnlyJob(EngineFile, CycleFile, + "TestEngineOnly-MultipleJobs-result2.vmod"); + simulation.AddJob(sim2); - var job3 = SimulationFactory.CreateTimeBasedEngineOnlyJob(EngineFile, CycleFile, - "TestEngineOnly-MultipleJobs-result3.vmod"); - sim.AddJob(job3); + var sim3 = SimulatorFactory.CreateTimeBasedEngineOnlyJob(EngineFile, CycleFile, + "TestEngineOnly-MultipleJobs-result3.vmod"); + simulation.AddJob(sim3); - sim.RunSimulation(); + simulation.RunSimulation(); // todo: Add additional assertions. Assert.Fail("Todo: Add additional assertions."); diff --git a/VectoCoreTest/Models/SimulationComponent/MockPorts.cs b/VectoCoreTest/Models/SimulationComponent/MockPorts.cs index 3678413f176aba0518420efed032ee5b92b0757d..d17ea03f20e81d6de3c006a771f2ced354386014 100644 --- a/VectoCoreTest/Models/SimulationComponent/MockPorts.cs +++ b/VectoCoreTest/Models/SimulationComponent/MockPorts.cs @@ -1,9 +1,10 @@ using System; using Common.Logging; using TUGraz.VectoCore.Models.Connector.Ports; +using TUGraz.VectoCore.Models.Connector.Ports.Impl; using TUGraz.VectoCore.Utils; -namespace TUGraz.VectoCore.Tests.Models.Simulation +namespace TUGraz.VectoCore.Tests.Models.SimulationComponent { public class MockTnOutPort : ITnOutPort { @@ -12,7 +13,7 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation public NewtonMeter Torque { get; set; } public RadianPerSecond AngularFrequency { get; set; } - public void Request(TimeSpan absTime, TimeSpan dt, NewtonMeter torque, RadianPerSecond angularFrequency) + public IResponse Request(TimeSpan absTime, TimeSpan dt, NewtonMeter torque, RadianPerSecond angularFrequency) { AbsTime = absTime; Dt = dt; @@ -20,6 +21,7 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation AngularFrequency = angularFrequency; LogManager.GetLogger(GetType()).DebugFormat("Request: absTime: {0}, dt: {1}, torque: {3}, engineSpeed: {4}", absTime, dt, torque, angularFrequency); + return new ResponseSuccess(); } } @@ -30,7 +32,7 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation public TimeSpan Dt { get; set; } public MeterPerSecond Velocity { get; set; } public double Gradient { get; set; } - public void Request(TimeSpan absTime, TimeSpan dt, MeterPerSecond velocity, double gradient) + public IResponse Request(TimeSpan absTime, TimeSpan dt, MeterPerSecond velocity, double gradient) { AbsTime = absTime; Dt = dt; @@ -38,6 +40,7 @@ namespace TUGraz.VectoCore.Tests.Models.Simulation Gradient = gradient; LogManager.GetLogger(GetType()).DebugFormat("Request: absTime: {0}, dt: {1}, velocity: {3}, gradient: {4}", absTime, dt, velocity, gradient); + return new ResponseSuccess(); } } } \ No newline at end of file