diff --git a/VectoCore/Configuration/Constants.cs b/VectoCore/Configuration/Constants.cs index 6d362522ff911f0d814d08cf801fe2a49d48d7b1..8ecb6cdbc6124f6ad807aaa20836c2ac83d7f8cd 100644 --- a/VectoCore/Configuration/Constants.cs +++ b/VectoCore/Configuration/Constants.cs @@ -76,7 +76,7 @@ namespace TUGraz.VectoCore.Configuration /// <summary> /// The initial search interval for the operating point search in the driver. /// </summary> - public static MeterPerSquareSecond OperatingPointInitialSearchIntervalAccelerating = 0.5.SI<MeterPerSquareSecond>(); + public static MeterPerSquareSecond OperatingPointInitialSearchIntervalAccelerating = 0.1.SI<MeterPerSquareSecond>(); } } } \ No newline at end of file diff --git a/VectoCore/Models/Simulation/DataBus/IMileageCounter.cs b/VectoCore/Models/Simulation/DataBus/IMileageCounter.cs index eedf4826fe993e000c6e8a012ef1918ba2e7e637..7e4a9db4767387e31b26b42a0049cd5198ff7c22 100644 --- a/VectoCore/Models/Simulation/DataBus/IMileageCounter.cs +++ b/VectoCore/Models/Simulation/DataBus/IMileageCounter.cs @@ -4,6 +4,6 @@ namespace TUGraz.VectoCore.Models.Simulation.DataBus { public interface IMileageCounter { - Meter Distance(); + Meter Distance { get; } } } \ No newline at end of file diff --git a/VectoCore/Models/Simulation/Impl/VectoRun.cs b/VectoCore/Models/Simulation/Impl/VectoRun.cs index 2524c659377be257940e6f6aeee3534fabb9a981..9769a6775efc451116ecf26af30826e641885ea4 100644 --- a/VectoCore/Models/Simulation/Impl/VectoRun.cs +++ b/VectoCore/Models/Simulation/Impl/VectoRun.cs @@ -1,4 +1,5 @@ -using TUGraz.VectoCore.Models.Connector.Ports; +using System; +using TUGraz.VectoCore.Models.Connector.Ports; using TUGraz.VectoCore.Models.Connector.Ports.Impl; using TUGraz.VectoCore.Models.Simulation.Data; using TUGraz.VectoCore.Utils; @@ -11,45 +12,39 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl public abstract class VectoRun : LoggingObject, IVectoRun { protected Second AbsTime = 0.SI<Second>(); - protected Second dt = 1.SI<Second>(); - - protected VectoRun(IVehicleContainer container) - { - Container = container; - CyclePort = container.GetCycleOutPort(); - } - protected SummaryFileWriter SumWriter { get; set; } - protected string JobFileName { get; set; } - protected string JobName { get; set; } - protected ISimulationOutPort CyclePort { get; set; } protected IModalDataWriter DataWriter { get; set; } protected IVehicleContainer Container { get; set; } + protected VectoRun(IVehicleContainer container) + { + Container = container; + CyclePort = container.GetCycleOutPort(); + } + public IVehicleContainer GetContainer() { return Container; } + public void Run() { Log.Info("VectoJob started running."); IResponse response; Initialize(); - do { response = DoSimulationStep(); if (response is ResponseSuccess) { Container.CommitSimulationStep(AbsTime, dt); - } - // todo set _dt to difference to next full second. - AbsTime += dt; + AbsTime += dt; + } } while (response is ResponseSuccess); Container.FinishSimulation(); diff --git a/VectoCore/Models/Simulation/Impl/VehicleContainer.cs b/VectoCore/Models/Simulation/Impl/VehicleContainer.cs index fd6d28f91eda1552d5361777d0a92d795e10cb58..d5db215b4be16ba1769bff857183c05eff514efd 100644 --- a/VectoCore/Models/Simulation/Impl/VehicleContainer.cs +++ b/VectoCore/Models/Simulation/Impl/VehicleContainer.cs @@ -148,7 +148,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl public void CommitSimulationStep(Second time, Second simulationInterval) { - Log.Info("VehicleContainer committing simulation. time: {0}, dist: {1}, speed: {2}", time, Distance(), VehicleSpeed()); + Log.Info("VehicleContainer committing simulation. time: {0}, dist: {1}, speed: {2}", time, Distance, VehicleSpeed()); foreach (var component in Components) { component.CommitSimulationStep(DataWriter); } @@ -175,13 +175,16 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl return new ReadOnlyCollection<VectoSimulationComponent>(Components); } - public Meter Distance() + public Meter Distance { - if (MilageCounter == null) { - Log.Warn("No MileageCounter in VehicleContainer. Distance cannot be measured."); - return 0.SI<Meter>(); + get + { + if (MilageCounter == null) { + Log.Warn("No MileageCounter in VehicleContainer. Distance cannot be measured."); + return 0.SI<Meter>(); + } + return MilageCounter.Distance; } - return MilageCounter.Distance(); } public IReadOnlyList<DrivingCycleData.DrivingCycleEntry> LookAhead(Meter lookaheadDistance) diff --git a/VectoCore/Models/SimulationComponent/Impl/DefaultDriverStrategy.cs b/VectoCore/Models/SimulationComponent/Impl/DefaultDriverStrategy.cs index 90e819da4d8a6968bec1ce09e6a257a7413dea90..c2bd91d43a77273763161d042d40f16e36518c97 100644 --- a/VectoCore/Models/SimulationComponent/Impl/DefaultDriverStrategy.cs +++ b/VectoCore/Models/SimulationComponent/Impl/DefaultDriverStrategy.cs @@ -47,7 +47,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { switch (CurrentDrivingMode) { case DrivingMode.DrivingModeDrive: - var currentDistance = Driver.DataBus.Distance(); + var currentDistance = Driver.DataBus.Distance; var nextAction = GetNextDrivingAction(currentDistance); if (nextAction != null && currentDistance.IsEqual(nextAction.ActionDistance)) { CurrentDrivingMode = DrivingMode.DrivingModeBrake; @@ -62,7 +62,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl } break; case DrivingMode.DrivingModeBrake: - if (Driver.DataBus.Distance() >= BrakeTrigger.TriggerDistance) { + if (Driver.DataBus.Distance >= BrakeTrigger.TriggerDistance) { CurrentDrivingMode = DrivingMode.DrivingModeDrive; DrivingModes[CurrentDrivingMode].ResetMode(); } @@ -218,7 +218,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl }); return response; } - var currentDistance = DriverStrategy.Driver.DataBus.Distance(); + var currentDistance = DriverStrategy.Driver.DataBus.Distance; if (Phase == BrakingPhase.Coast) { var breakingDistance = DriverStrategy.Driver.ComputeDecelerationDistance(DriverStrategy.BrakeTrigger.NextTargetSpeed); if (currentDistance + ds > DriverStrategy.BrakeTrigger.TriggerDistance - breakingDistance) { diff --git a/VectoCore/Models/SimulationComponent/Impl/Driver.cs b/VectoCore/Models/SimulationComponent/Impl/Driver.cs index 9d60803675d53d0c432634bfb51c7257c5b3b660..3c709ad50966823025c940ab946435e9c5cf84f6 100644 --- a/VectoCore/Models/SimulationComponent/Impl/Driver.cs +++ b/VectoCore/Models/SimulationComponent/Impl/Driver.cs @@ -61,7 +61,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl Log.Debug("==== DRIVER Request ===="); Log.Debug( "Request: absTime: {0}, ds: {1}, targetVelocity: {2}, gradient: {3} | distance: {4}, velocity: {5}", absTime, ds, - targetVelocity, gradient, DataBus.Distance(), DataBus.VehicleSpeed()); + targetVelocity, gradient, DataBus.Distance, DataBus.VehicleSpeed()); var retVal = DriverStrategy.Request(absTime, ds, targetVelocity, gradient); //DoHandleRequest(absTime, ds, targetVelocity, gradient); @@ -397,15 +397,16 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl MeterPerSquareSecond acceleration, IResponse initialResponse, bool coasting = false) { var debug = new List<dynamic>(); - var searchInterval = Constants.SimulationSettings.OperatingPointInitialSearchIntervalAccelerating; - - // double the searchInterval until a good interval was found - var intervalFactor = 2.0; - var retVal = new OperatingPoint() { Acceleration = acceleration, SimulationDistance = ds }; + var retVal = new OperatingPoint { Acceleration = acceleration, SimulationDistance = ds }; var actionRoll = !DataBus.ClutchClosed(absTime); + var searchInterval = Constants.SimulationSettings.OperatingPointInitialSearchIntervalAccelerating; + + var curve = DriverData.AccelerationCurve.Lookup(DataBus.VehicleSpeed()); + Func<MeterPerSquareSecond, MeterPerSquareSecond> modifySearchInterval = x => x * 2; + Watt origDelta = null; if (actionRoll) { initialResponse.Switch(). @@ -413,7 +414,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl Default(r => { throw new VectoSimulationException("Unknown response type. {0}", r); }); - //searchInterval = origDelta; } else { initialResponse.Switch(). Case<ResponseOverload>(r => origDelta = r.Delta). // search operating point in drive action after overload @@ -426,26 +426,33 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl var retryCount = 0; do { - debug.Add(new { delta, acceleration = retVal.Acceleration, searchInterval, intervalFactor }); + debug.Add(new { delta, acceleration = retVal.Acceleration, searchInterval }); // check if a correct searchInterval was found (when the delta changed signs, we stepped through the 0-point) // from then on the searchInterval can be bisected. if (origDelta.Sign() != delta.Sign()) { - intervalFactor = 0.5; + modifySearchInterval = x => x / 2; } - searchInterval *= intervalFactor; + searchInterval = modifySearchInterval(searchInterval); retVal.Acceleration += searchInterval * -delta.Sign(); + if (retVal.Acceleration < (curve.Deceleration - Constants.SimulationSettings.MinimumAcceleration) + || retVal.Acceleration > (curve.Acceleration + Constants.SimulationSettings.MinimumAcceleration)) { + throw new VectoSimulationException( + "Could not find an operating point: operating point outside of driver acceleration limits."); + } + // TODO: move to driving mode // check for minimum acceleration, add some safety margin due to search - if (!coasting && retVal.Acceleration.Abs() < Constants.SimulationSettings.MinimumAcceleration.Value() / 5.0 + if (!coasting && retVal.Acceleration.Abs() < Constants.SimulationSettings.MinimumAcceleration / 5.0 && searchInterval.Abs() < Constants.SimulationSettings.MinimumAcceleration / 20.0) { throw new VectoSimulationException("Could not achieve minimum acceleration"); } var tmp = ComputeTimeInterval(retVal.Acceleration, ds); retVal.SimulationInterval = tmp.SimulationInterval; + retVal.SimulationDistance = tmp.SimulationDistance; var response = (ResponseDryRun)Next.Request(absTime, retVal.SimulationInterval, retVal.Acceleration, gradient, true); delta = actionRoll ? response.GearboxPowerRequest : (coasting ? response.DeltaDragLoad : response.DeltaFullLoad); diff --git a/VectoCore/Models/SimulationComponent/Impl/Vehicle.cs b/VectoCore/Models/SimulationComponent/Impl/Vehicle.cs index 0bab84f5e95b62ecce078ffc60e05f87c6595463..0406972a9787124f554349ea9efe496b89d7eac2 100644 --- a/VectoCore/Models/SimulationComponent/Impl/Vehicle.cs +++ b/VectoCore/Models/SimulationComponent/Impl/Vehicle.cs @@ -2,9 +2,9 @@ using System.Collections.Generic; using TUGraz.VectoCore.Models.Connector.Ports; using TUGraz.VectoCore.Models.Declaration; +using TUGraz.VectoCore.Models.Simulation; using TUGraz.VectoCore.Models.Simulation.Data; using TUGraz.VectoCore.Models.Simulation.DataBus; -using TUGraz.VectoCore.Models.Simulation.Impl; using TUGraz.VectoCore.Models.SimulationComponent.Data; using TUGraz.VectoCore.Utils; @@ -13,20 +13,44 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl public class Vehicle : VectoSimulationComponent, IVehicle, IMileageCounter, IFvInPort, IDriverDemandOutPort { private IFvOutPort _nextInstance; - private VehicleState _previousState; private VehicleState _currentState; - private readonly VehicleData _data; - public Vehicle(VehicleContainer container, VehicleData data) : base(container) + public MeterPerSecond VehicleSpeed() + { + return _previousState.Velocity; + } + + public Kilogram VehicleMass() + { + return _data.TotalCurbWeight(); + } + + public Kilogram VehicleLoading() + { + return _data.Loading; + } + + public Kilogram TotalMass() + { + return _data.TotalVehicleWeight(); + } + + public Meter Distance + { + get { return _previousState.Distance; } + } + + + public Vehicle(IVehicleContainer container, VehicleData data) : base(container) { _data = data; _previousState = new VehicleState { Distance = 0.SI<Meter>(), Velocity = 0.SI<MeterPerSecond>() }; _currentState = new VehicleState { Distance = 0.SI<Meter>(), Velocity = 0.SI<MeterPerSecond>() }; } - public Vehicle(VehicleContainer container, VehicleData data, double initialVelocity) : this(container, data) + public Vehicle(IVehicleContainer container, VehicleData data, double initialVelocity) : this(container, data) { _previousState.Velocity = initialVelocity.SI<MeterPerSecond>(); } @@ -46,18 +70,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl _nextInstance = other; } - protected override void DoWriteModalResults(IModalDataWriter writer) + public IResponse Initialize(MeterPerSecond vehicleSpeed, Radian roadGradient) { - writer[ModalResultField.v_act] = (_previousState.Velocity + _currentState.Velocity) / 2; - writer[ModalResultField.dist] = _currentState.Distance; - - // hint: take care to use correct velocity when writing the P... values in moddata - } + _previousState = new VehicleState { Distance = 0.SI<Meter>(), Velocity = vehicleSpeed }; + _currentState = new VehicleState { Distance = 0.SI<Meter>(), Velocity = vehicleSpeed }; - protected override void DoCommitSimulationStep() - { - _previousState = _currentState; - _currentState = new VehicleState(); + var vehicleAccelerationForce = RollingResistance(roadGradient) + AirDragResistance() + SlopeResistance(roadGradient); + return _nextInstance.Initialize(vehicleAccelerationForce, vehicleSpeed); } public IResponse Request(Second absTime, Second dt, MeterPerSquareSecond accelleration, Radian gradient, @@ -75,17 +94,21 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl + SlopeResistance(gradient); var retval = _nextInstance.Request(absTime, dt, vehicleAccelerationForce, _currentState.Velocity, dryRun); - //retval.VehiclePowerRequest = return retval; } - public IResponse Initialize(MeterPerSecond vehicleSpeed, Radian roadGradient) + protected override void DoWriteModalResults(IModalDataWriter writer) { - _previousState = new VehicleState { Distance = 0.SI<Meter>(), Velocity = vehicleSpeed }; - _currentState = new VehicleState { Distance = 0.SI<Meter>(), Velocity = vehicleSpeed }; + writer[ModalResultField.v_act] = (_previousState.Velocity + _currentState.Velocity) / 2; + writer[ModalResultField.dist] = _currentState.Distance; - var vehicleAccelerationForce = RollingResistance(roadGradient) + AirDragResistance() + SlopeResistance(roadGradient); - return _nextInstance.Initialize(vehicleAccelerationForce, vehicleSpeed); + // todo hint: take care to use correct velocity when writing the P... values in moddata + } + + protected override void DoCommitSimulationStep() + { + _previousState = _currentState; + _currentState = new VehicleState(); } protected Newton RollingResistance(Radian gradient) @@ -207,26 +230,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return retVal; } - public MeterPerSecond VehicleSpeed() - { - return _previousState.Velocity; - } - - public Kilogram VehicleMass() - { - return _data.TotalCurbWeight(); - } - - public Kilogram VehicleLoading() - { - return _data.Loading; - } - - public Kilogram TotalMass() - { - return _data.TotalVehicleWeight(); - } - public class VehicleState { @@ -234,10 +237,5 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl public Second dt; public Meter Distance; } - - public Meter Distance() - { - return _previousState.Distance; - } } } \ No newline at end of file diff --git a/VectoCoreTest/Integration/DriverStrategy/DriverStrategyTest.cs b/VectoCoreTest/Integration/DriverStrategy/DriverStrategyTest.cs index 0d20f7630e6b2ddfd4acbade5e29ca453dbbb3d5..2dca7fc2b3b428bebf88125c3f3974bf761cc81f 100644 --- a/VectoCoreTest/Integration/DriverStrategy/DriverStrategyTest.cs +++ b/VectoCoreTest/Integration/DriverStrategy/DriverStrategyTest.cs @@ -32,10 +32,11 @@ namespace TUGraz.VectoCore.Tests.Integration.DriverStrategy [TestMethod] public void Accelerate_0_80_level() { - var cycle = CreateCycleData(new string[] { - " 0, 0,0,2", - " 0,80,0,0", - "900,80,0,0", + var cycle = CreateCycleData(new[] { + // <s>,<v>,<grad>,<stop> + " 0, 0, 0, 2", + " 0, 80, 0, 0", + "900, 80, 0, 0", }); var run = CreatePowerTrain(cycle, "DriverStrategy_Accelerate_0_80_level.vmod"); @@ -47,12 +48,13 @@ namespace TUGraz.VectoCore.Tests.Integration.DriverStrategy [TestMethod] public void Accelerate_80_0_level() { - var cycle = CreateCycleData(new string[] { - " 0,80,0,0", - "2500, 0,0,0", + var cycle = CreateCycleData(new[] { + // <s>,<v>,<grad>,<stop> + " 0, 80, 0, 0", + "900, 0, 0, 0", }); - var run = CreatePowerTrain(cycle, "DriverStrategy_Accelerate_80_0_level.vmod"); + var run = CreatePowerTrain(cycle, "DriverStrategy_Accelerate_0_80_level.vmod"); run.Run(); } diff --git a/VectoCoreTest/Integration/SimulationRuns/FullPowertrain.cs b/VectoCoreTest/Integration/SimulationRuns/FullPowertrain.cs index 35fe1c8548f32527af15e756dadaab97989be2f5..44a1c31705a5ace5b993f1d8c4ec277cb6779379 100644 --- a/VectoCoreTest/Integration/SimulationRuns/FullPowertrain.cs +++ b/VectoCoreTest/Integration/SimulationRuns/FullPowertrain.cs @@ -72,7 +72,7 @@ namespace TUGraz.VectoCore.Tests.Integration.SimulationRuns container.Gear = 1; var cnt = 0; - while (!(response is ResponseCycleFinished) && container.Distance().Value() < 17000) { + while (!(response is ResponseCycleFinished) && container.Distance < 17000) { response = cyclePort.Request(absTime, ds); response.Switch(). Case<ResponseDrivingCycleDistanceExceeded>(r => ds = r.MaxDistance). @@ -133,7 +133,7 @@ namespace TUGraz.VectoCore.Tests.Integration.SimulationRuns container.Gear = 1; var cnt = 0; - while (!(response is ResponseCycleFinished) && container.Distance().Value() < 17000) { + while (!(response is ResponseCycleFinished) && container.Distance < 17000) { Log.Info("Test New Request absTime: {0}, ds: {1}", absTime, ds); try { response = cyclePort.Request(absTime, ds); @@ -204,7 +204,7 @@ namespace TUGraz.VectoCore.Tests.Integration.SimulationRuns //container.Gear = 1; var cnt = 0; - while (!(response is ResponseCycleFinished) && container.Distance().Value() < 17000) { + while (!(response is ResponseCycleFinished) && container.Distance < 17000) { Log.Info("Test New Request absTime: {0}, ds: {1}", absTime, ds); try { response = cyclePort.Request(absTime, ds); diff --git a/VectoCoreTest/Integration/SimulationRuns/MinimalPowertrain.cs b/VectoCoreTest/Integration/SimulationRuns/MinimalPowertrain.cs index 6144b90c232264bf6fac996cece4c3ce5ab9a789..39d85768b649e4e8e6ec1f30814daee7aae9285a 100644 --- a/VectoCoreTest/Integration/SimulationRuns/MinimalPowertrain.cs +++ b/VectoCoreTest/Integration/SimulationRuns/MinimalPowertrain.cs @@ -124,11 +124,11 @@ namespace TUGraz.VectoCore.Tests.Integration.SimulationRuns vehicleContainer.Gear = 1; var cnt = 0; - while (!(response is ResponseCycleFinished) && vehicleContainer.Distance().Value() < 17000) { + while (!(response is ResponseCycleFinished) && vehicleContainer.Distance < 17000) { response = cyclePort.Request(absTime, ds); response.Switch(). Case<ResponseDrivingCycleDistanceExceeded>(r => ds = r.MaxDistance). - Case<ResponseCycleFinished>(r => { }). + Case<ResponseCycleFinished>(r => {}). Case<ResponseSuccess>(r => { vehicleContainer.CommitSimulationStep(absTime, r.SimulationInterval); absTime += r.SimulationInterval; @@ -188,7 +188,7 @@ namespace TUGraz.VectoCore.Tests.Integration.SimulationRuns vehicleContainer.Gear = 1; var ds = Constants.SimulationSettings.DriveOffDistance; - while (vehicleContainer.Distance().Value() < 100) { + while (vehicleContainer.Distance < 100) { var response = cyclePort.Request(absTime, ds); response.Switch(). Case<ResponseDrivingCycleDistanceExceeded>(r => ds = r.MaxDistance). diff --git a/VectoCoreTest/Utils/MockVehicle.cs b/VectoCoreTest/Utils/MockVehicle.cs index a7fb29e08903366a1ab09e2d39bdd607432466b2..012572e95ca3c1469ad90002feddd8b3a1226780 100644 --- a/VectoCoreTest/Utils/MockVehicle.cs +++ b/VectoCoreTest/Utils/MockVehicle.cs @@ -80,9 +80,9 @@ namespace TUGraz.VectoCore.Tests.Utils public Radian gradient; } - public Meter Distance() + public Meter Distance { - return 0.SI<Meter>(); + get { return 0.SI<Meter>(); } } } } \ No newline at end of file