diff --git a/VectoCore/Models/Connector/Ports/IResponse.cs b/VectoCore/Models/Connector/Ports/IResponse.cs index d6d68d495dfab355caa637982c081eb2028d843b..bdaec9e0cdd205e27e58567346057701ec60f00b 100644 --- a/VectoCore/Models/Connector/Ports/IResponse.cs +++ b/VectoCore/Models/Connector/Ports/IResponse.cs @@ -1,21 +1,10 @@ using System; +using System.Diagnostics; using System.Security.Cryptography.X509Certificates; using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.Connector.Ports { - public enum ResponseType - { - Success, - CycleFinished, - FailOverload, - FailTimeInterval, - DrivingCycleDistanceExceeded, - DryRun, - GearShift - } - - /// <summary> /// Defines an interface for a Response. /// </summary> @@ -23,8 +12,6 @@ namespace TUGraz.VectoCore.Models.Connector.Ports { Second SimulationInterval { get; set; } - ResponseType ResponseType { get; } - Watt EnginePowerRequest { get; set; } Watt ClutchPowerRequest { get; set; } diff --git a/VectoCore/Models/Connector/Ports/Impl/Response.cs b/VectoCore/Models/Connector/Ports/Impl/Response.cs index 60dbf2593c0a0e23e6c1f257d5db4b7f58fb54ad..55929de638f68a9a6519d32f26917e8008bf9a9b 100644 --- a/VectoCore/Models/Connector/Ports/Impl/Response.cs +++ b/VectoCore/Models/Connector/Ports/Impl/Response.cs @@ -1,4 +1,3 @@ -using System; using TUGraz.VectoCore.Utils; namespace TUGraz.VectoCore.Models.Connector.Ports.Impl @@ -7,8 +6,6 @@ namespace TUGraz.VectoCore.Models.Connector.Ports.Impl { public Second SimulationInterval { get; set; } - public abstract ResponseType ResponseType { get; } - public Watt EnginePowerRequest { get; set; } public Watt ClutchPowerRequest { get; set; } @@ -25,78 +22,51 @@ namespace TUGraz.VectoCore.Models.Connector.Ports.Impl /// <summary> /// Response when the Cycle is finished. /// </summary> - public class ResponseCycleFinished : AbstractResponse - { - public override ResponseType ResponseType - { - get { return ResponseType.CycleFinished; } - } - } + public class ResponseCycleFinished : AbstractResponse {} /// <summary> /// Response when a request was successful. /// </summary> - public class ResponseSuccess : AbstractResponse + public class ResponseSuccess : AbstractResponse {} + + /// <summary> + /// Response when the request resulted in an engine overload. + /// </summary> + public class ResponseEngineOverload : AbstractResponse { - public override ResponseType ResponseType - { - get { return ResponseType.Success; } - } + public Watt Delta { get; set; } + public double Gradient { get; set; } } /// <summary> /// Response when the request resulted in an engine overload. /// </summary> - public class ResponseFailOverload : AbstractResponse + public class ResponseGearboxOverload : AbstractResponse { public Watt Delta { get; set; } public double Gradient { get; set; } - - public override ResponseType ResponseType - { - get { return ResponseType.FailOverload; } - } } + /// <summary> /// Response when the request should have another time interval. /// </summary> public class ResponseFailTimeInterval : AbstractResponse { public Second DeltaT { get; set; } - - public override ResponseType ResponseType - { - get { return ResponseType.FailTimeInterval; } - } } public class ResponseDrivingCycleDistanceExceeded : AbstractResponse { public Meter MaxDistance { get; set; } - - public override ResponseType ResponseType - { - get { return ResponseType.DrivingCycleDistanceExceeded; } - } } internal class ResponseDryRun : AbstractResponse { public Watt EngineDeltaFullLoad { get; set; } public Watt EngineDeltaDragLoad { get; set; } - - public override ResponseType ResponseType - { - get { return ResponseType.DryRun; } - } + public Watt GearboxDeltaFullLoad { get; set; } } - internal class ResponseGearShift : AbstractResponse - { - public override ResponseType ResponseType - { - get { return ResponseType.GearShift; } - } - } + internal class ResponseGearShift : AbstractResponse {} } \ No newline at end of file diff --git a/VectoCore/Models/Simulation/Impl/DistanceRun.cs b/VectoCore/Models/Simulation/Impl/DistanceRun.cs index 7b037b12ca99dd17e90ba0a3716c6315d5d91102..4f0b205b7cf93159cb4d73a2ae9b7c4f0238d893 100644 --- a/VectoCore/Models/Simulation/Impl/DistanceRun.cs +++ b/VectoCore/Models/Simulation/Impl/DistanceRun.cs @@ -25,20 +25,10 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl do { response = CyclePort.Request(AbsTime, ds); - switch (response.ResponseType) { - case ResponseType.Success: - requestDone = true; - break; - case ResponseType.CycleFinished: - requestDone = true; - break; - case ResponseType.DrivingCycleDistanceExceeded: - var distanceResponse = response as ResponseDrivingCycleDistanceExceeded; - if (distanceResponse != null) { - ds = distanceResponse.MaxDistance; - } - break; - } + response.Switch(). + Case<ResponseSuccess>(_ => requestDone = true). + Case<ResponseCycleFinished>(_ => requestDone = true). + Case<ResponseDrivingCycleDistanceExceeded>(r => { ds = r.MaxDistance; }); } while (!requestDone); //while (response is ResponseFailTimeInterval) { diff --git a/VectoCore/Models/Simulation/Impl/VectoRun.cs b/VectoCore/Models/Simulation/Impl/VectoRun.cs index b6feaf95763ddc640450128ca5f386f3eb6816fc..7ec4b31e23d9acb69945e0e857642301d6a73efb 100644 --- a/VectoCore/Models/Simulation/Impl/VectoRun.cs +++ b/VectoCore/Models/Simulation/Impl/VectoRun.cs @@ -45,7 +45,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Impl Initialize(); do { response = DoSimulationStep(); - if (response.ResponseType == ResponseType.Success) { + if (response is ResponseSuccess) { Container.CommitSimulationStep(AbsTime, dt); } diff --git a/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs b/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs index e6019db04fb6abe478335f65e6ce2ca73c2697ef..eb0e39937d882c2ce90a255db25aa38f55c5dbef 100644 --- a/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs +++ b/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs @@ -105,7 +105,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl } if (!_currentState.EnginePower.IsEqual(requestedEnginePower, Constants.SimulationSettings.EngineFLDPowerTolerance)) { - return new ResponseFailOverload { + return new ResponseEngineOverload { Delta = (requestedEnginePower - _currentState.EnginePower), EnginePowerRequest = requestedEnginePower }; diff --git a/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs b/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs index 9c6c0b5456e3b4919f3c89f23183e64f4e98b890..bef6f27ce43542778faaf707d57d0da750b2132b 100644 --- a/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs +++ b/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs @@ -96,7 +96,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl } if (PreviousState.Distance + ds > CycleIntervalIterator.RightSample.Distance) { - // only drive until next sample point in cycle // only drive until next sample point in cycle return new ResponseDrivingCycleDistanceExceeded { MaxDistance = CycleIntervalIterator.RightSample.Distance - PreviousState.Distance @@ -186,7 +185,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl protected override void DoCommitSimulationStep() { - if (CurrentState.Response.ResponseType != ResponseType.Success) { + if (!(CurrentState.Response is ResponseSuccess)) { throw new VectoSimulationException("Previous request did not succeed!"); } diff --git a/VectoCore/Models/SimulationComponent/Impl/Driver.cs b/VectoCore/Models/SimulationComponent/Impl/Driver.cs index 835681f52ae7f9551acef151584b3daf0d151bbe..fddfa9d21cda4751252b2f500bc95cf9fd9a47e3 100644 --- a/VectoCore/Models/SimulationComponent/Impl/Driver.cs +++ b/VectoCore/Models/SimulationComponent/Impl/Driver.cs @@ -67,18 +67,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl Log.Debug("==== DRIVER Request ===="); Log.DebugFormat( "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 = DoHandleRequest(absTime, ds, targetVelocity, gradient); CurrentState.Response = retVal; - - switch (retVal.ResponseType) { - case ResponseType.FailOverload: - - break; - } return retVal; } @@ -86,13 +79,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl public IResponse Request(Second absTime, Second dt, MeterPerSecond targetVelocity, Radian gradient) { Log.Debug("==== DRIVER Request ===="); - Log.DebugFormat("Request: absTime: {0}, dt: {1}, targetVelocity: {2}, gradient: {3}", absTime, dt, targetVelocity - , gradient); + Log.DebugFormat("Request: absTime: {0}, dt: {1}, targetVelocity: {2}, gradient: {3}", absTime, dt, targetVelocity, + gradient); var retVal = DoHandleRequest(absTime, dt, targetVelocity, gradient); CurrentState.Response = retVal; - - //switch (retVal.ResponseType) {} return retVal; } @@ -186,12 +177,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl CurrentState.Acceleration); var retVal = Next.Request(absTime, CurrentState.dt, CurrentState.Acceleration, gradient); CurrentState.Response = retVal; - switch (retVal.ResponseType) { - case ResponseType.Success: - retVal.SimulationInterval = CurrentState.dt; - return retVal; + if (retVal is ResponseSuccess) { + retVal.SimulationInterval = CurrentState.dt; + } else { + Log.DebugFormat("unhandled response from powertrain: {0}", retVal); } - Log.DebugFormat("unhandled response from powertrain: {0}", retVal); + return retVal; //new ResponseDrivingCycleDistanceExceeded() { SimulationInterval = CurrentState.dt }; } @@ -244,29 +235,46 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return new ResponseFailTimeInterval(); } + IResponse retVal = null; do { - var retVal = Next.Request(absTime, CurrentState.dt, CurrentState.Acceleration, gradient); - switch (retVal.ResponseType) { - case ResponseType.Success: - retVal.SimulationInterval = CurrentState.dt; - return retVal; - case ResponseType.FailOverload: - var overloadResponse = retVal as ResponseFailOverload; - if (overloadResponse != null && overloadResponse.Delta < 0) { + var response = Next.Request(absTime, CurrentState.dt, CurrentState.Acceleration, gradient); + response.Switch(). + Case<ResponseSuccess>(r => { + r.SimulationInterval = CurrentState.dt; + retVal = r; + }). + Case<ResponseEngineOverload>(r => { + if (r != null && r.Delta < 0) { // if Delta is negative we are already below the Drag-load curve. activate breaks - return DoBreak(absTime, ds, gradient, targetVelocity); + retVal = DoBreak(absTime, ds, gradient, targetVelocity); + } else { + var doAccelerate = (DataBus.VehicleSpeed() - targetVelocity).Abs() > 0.1 * targetVelocity; + + if (!SearchOperatingPoint(absTime, ref ds, gradient, r, accelerating: doAccelerate)) { + throw new VectoSimulationException("could not find operating point"); + } + Log.DebugFormat("Found operating point for Drive/Accelerate. dt: {0}, acceleration: {1}, doAccelerate: {2}", + CurrentState.dt, CurrentState.Acceleration, doAccelerate); } - var doAccelerate = (DataBus.VehicleSpeed() - targetVelocity).Abs() > 0.1 * targetVelocity; - - var success = SearchOperatingPoint(absTime, ref ds, gradient, retVal, accelerating: doAccelerate); - if (!success) { - throw new VectoSimulationException("could not find operating point"); + }). + Case<ResponseGearShift>(() => { }). + Case<ResponseGearboxOverload>(r => { + if (r != null && r.Delta < 0) { + // if Delta is negative we are below the Drag-load curve: activate breaks + retVal = DoBreak(absTime, ds, gradient, targetVelocity); + } else { + var doAccelerate = (DataBus.VehicleSpeed() - targetVelocity).Abs() > 0.1 * targetVelocity; + + if (!SearchOperatingPoint(absTime, ref ds, gradient, r, accelerating: doAccelerate)) { + throw new VectoSimulationException("could not find operating point"); + } + Log.DebugFormat("Found operating point for Drive/Accelerate. dt: {0}, acceleration: {1}, doAccelerate: {2}", + CurrentState.dt, CurrentState.Acceleration, doAccelerate); } - Log.DebugFormat("Found operating point for Drive/Accelerate. dt: {0}, acceleration: {1}, doAccelerate: {2}", - CurrentState.dt, - CurrentState.Acceleration, doAccelerate); - - break; + }). + Default(r => { throw new VectoException(string.Format("Unknown Response: {0}", r)); }); + if (retVal != null) { + return retVal; } } while (CurrentState.RetryCount++ < Constants.SimulationSettings.DriverSearchLoopThreshold); @@ -359,12 +367,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl CurrentState.Acceleration); var retVal = Next.Request(absTime, CurrentState.dt, CurrentState.Acceleration, gradient); CurrentState.Response = retVal; - switch (retVal.ResponseType) { - case ResponseType.Success: - retVal.SimulationInterval = CurrentState.dt; - return retVal; - } - Log.DebugFormat("unhandled response from powertrain: {0}", retVal); + + retVal.Switch(). + Case<ResponseSuccess>(r => r.SimulationInterval = CurrentState.dt). + Default(() => Log.DebugFormat("unhandled response from powertrain: {0}", retVal)); + return retVal; //new ResponseDrivingCycleDistanceExceeded() { SimulationInterval = CurrentState.dt }; } @@ -397,20 +404,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl } do { - Watt delta; + var delta = 0.SI<Watt>(); ds = originalDs; - switch (response.ResponseType) { - case ResponseType.FailOverload: - delta = ((ResponseFailOverload)response).Delta; - break; - case ResponseType.DryRun: - delta = coasting - ? -((ResponseDryRun)response).EngineDeltaDragLoad - : ((ResponseDryRun)response).EngineDeltaFullLoad; - break; - default: - throw new VectoSimulationException(string.Format("Unknown response type. {0}", response)); - } + response.Switch(). + Case<ResponseEngineOverload>(r => delta = r.Delta). + Case<ResponseDryRun>(r => delta = coasting ? -r.EngineDeltaDragLoad : r.EngineDeltaFullLoad). + Default(r => { throw new VectoSimulationException(string.Format("Unknown response type. {0}", r)); }); exceeded.Add(delta); acceleration.Add(CurrentState.Acceleration.Value()); @@ -558,8 +557,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl protected override void DoCommitSimulationStep() { - if (CurrentState.Response.ResponseType != ResponseType.Success) { - throw new VectoSimulationException("Previois request did not succeed!"); + if (!(CurrentState.Response is ResponseSuccess)) { + throw new VectoSimulationException("Previous request did not succeed!"); } CurrentState.RetryCount = 0; CurrentState.Response = null; diff --git a/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs b/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs index 6626e75aae7ee7cf9d6e23d732223121d872526a..157ed811ebf69258b0e348c01a10b48c7b818bdd 100644 --- a/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs +++ b/VectoCore/Models/SimulationComponent/Impl/Gearbox.cs @@ -77,8 +77,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl // * SkipGears (when already shifting to next gear, check if torque reserve is fullfilled for the overnext gear and eventually shift to it) // * MT, AMT and AT .... different behaviour! + //Special Behaviour: When Gear is 0 (no gear set) or the speed is 0 (not rotating) a zero-request is applied. if (Gear == 0 || outEngineSpeed.IsEqual(0)) { - return Next.Request(absTime, dt, 0.SI<NewtonMeter>(), 0.SI<PerSecond>()); + return Next.Request(absTime, dt, 0.SI<NewtonMeter>(), 0.SI<PerSecond>(), dryRun); } bool gearChanged; @@ -114,9 +115,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl var maxTorque = CurrentGear.FullLoadCurve.FullLoadStationaryTorque(inEngineSpeed); if (inTorque.Abs() > maxTorque) { _gear = _previousGear; - return new ResponseFailOverload { + return new ResponseGearboxOverload { + Delta = (inTorque.Abs() - maxTorque) * inEngineSpeed, GearboxPowerRequest = inTorque * inEngineSpeed, - Delta = Math.Sign(inTorque.Value()) * (inTorque.Abs() - maxTorque) * inEngineSpeed }; } @@ -127,7 +128,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl return new ResponseGearShift { SimulationInterval = Data.TractionInterruption }; } - return Next.Request(absTime, dt, inTorque, inEngineSpeed); + var response = Next.Request(absTime, dt, inTorque, inEngineSpeed, dryRun); + response.GearboxPowerRequest = inTorque * inEngineSpeed; + + response.Switch(). + Case<ResponseDryRun>(r => r.GearboxDeltaFullLoad = (maxTorque - inTorque) * inEngineSpeed); + + return response; } @@ -213,7 +220,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl writer[ModalResultField.Gear] = _gear; writer[ModalResultField.PlossGB] = _loss; - // todo Gearbox PaGB rotational acceleration power: Gearbox + // todo Gearbox PaGB rotational acceleration power in moddata writer[ModalResultField.PaGB] = 0.SI(); } diff --git a/VectoCore/Utils/SI.cs b/VectoCore/Utils/SI.cs index 518934d0031089559d26a36d61308e63300bca9e..ec1c2254af1c8003c38a139d4e1e38ce9a65f2f8 100644 --- a/VectoCore/Utils/SI.cs +++ b/VectoCore/Utils/SI.cs @@ -1506,6 +1506,7 @@ namespace TUGraz.VectoCore.Utils /// </summary> /// <param name="si">The si.</param> /// <returns></returns> + [DebuggerHidden] public bool HasEqualUnit(SI si) { Contract.Requires(si != null); diff --git a/VectoCore/Utils/SwitchExtension.cs b/VectoCore/Utils/SwitchExtension.cs new file mode 100644 index 0000000000000000000000000000000000000000..8694ff548c8e2e726c30065f0d02069a69f422a7 --- /dev/null +++ b/VectoCore/Utils/SwitchExtension.cs @@ -0,0 +1,57 @@ +using System; +using System.Runtime.CompilerServices; + +namespace TUGraz.VectoCore.Utils +{ + /// <summary> + /// Extension Methods for Creating a Switch-Case Construct on Types. + /// </summary> + /// <remarks> + /// Adapted for VECTO. Created by Virtlink. Original source code on GitHub: <see href="https://gist.github.com/Virtlink/8722649"/>. + /// </remarks> + public static class SwitchExtension + { + public static Switcher<T> Switch<T>(this T self) + { + return new Switcher<T>(self); + } + + public class Switcher<T> + { + private readonly T _value; + private bool _handled; + + internal Switcher(T value) + { + _value = value; + _handled = false; + } + + public Switcher<T> Case<TTarget>(Action action) where TTarget : T + { + return Case<TTarget>(_ => action()); + } + + public Switcher<T> Case<TTarget>(Action<TTarget> action) where TTarget : T + { + if (!_handled && _value is TTarget) { + action((TTarget)_value); + _handled = true; + } + return this; + } + + public void Default(Action action) + { + Default(_ => action()); + } + + public void Default(Action<T> action) + { + if (!_handled) { + action(_value); + } + } + } + } +} \ No newline at end of file diff --git a/VectoCore/VectoCore.csproj b/VectoCore/VectoCore.csproj index 99a7378db2808be327b629dcabf858eef7874ecc..a11981817aaeb52039b59e0ad879a272aafc0dd2 100644 --- a/VectoCore/VectoCore.csproj +++ b/VectoCore/VectoCore.csproj @@ -245,6 +245,7 @@ <Compile Include="Models\Simulation\IVehicleContainer.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Utils\StringExtensionMethods.cs" /> + <Compile Include="Utils\SwitchExtension.cs" /> <Compile Include="Utils\VectoCSVFile.cs" /> <Compile Include="Utils\VectoMath.cs" /> <Compile Include="Utils\DelauneyMap.cs" /> diff --git a/VectoCoreTest/Integration/SimulationRuns/FullPowertrain.cs b/VectoCoreTest/Integration/SimulationRuns/FullPowertrain.cs index a310a54ec2ed815765ce4c27edaad2bc12d8e629..d2ade7b1c553ebd6e688f873f8dcc67118c36bef 100644 --- a/VectoCoreTest/Integration/SimulationRuns/FullPowertrain.cs +++ b/VectoCoreTest/Integration/SimulationRuns/FullPowertrain.cs @@ -5,7 +5,6 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using TUGraz.VectoCore.Configuration; using TUGraz.VectoCore.FileIO.Reader; using TUGraz.VectoCore.FileIO.Reader.Impl; -using TUGraz.VectoCore.Models.Connector.Ports; using TUGraz.VectoCore.Models.Connector.Ports.Impl; using TUGraz.VectoCore.Models.Declaration; using TUGraz.VectoCore.Models.Simulation.Data; @@ -64,51 +63,40 @@ namespace TUGraz.VectoCore.Tests.Integration.SimulationRuns cyclePort.Initialize(); - var absTime = 0.SI<Second>(); - var response = cyclePort.Request(absTime, 1.SI<Meter>()); + container.Gear = 0; + var absTime = 0.SI<Second>(); + var ds = Constants.SimulationSettings.DriveOffDistance; + var response = cyclePort.Request(absTime, ds); Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); - container.CommitSimulationStep(absTime, response.SimulationInterval); absTime += response.SimulationInterval; container.Gear = 1; - var ds = Constants.SimulationSettings.DriveOffDistance; var cnt = 0; - var doRun = true; - while (doRun && container.Distance().Value() < 17000) { + while (!(response is ResponseCycleFinished) && container.Distance().Value() < 17000) { response = cyclePort.Request(absTime, ds); - - switch (response.ResponseType) { - case ResponseType.DrivingCycleDistanceExceeded: - var rsp = response as ResponseDrivingCycleDistanceExceeded; - ds = rsp.MaxDistance; - continue; - case ResponseType.CycleFinished: - doRun = false; - break; - } - if (doRun) { - Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); - - container.CommitSimulationStep(absTime, response.SimulationInterval); - absTime += response.SimulationInterval; - - ds = container.VehicleSpeed().IsEqual(0) - ? Constants.SimulationSettings.DriveOffDistance - : (Constants.SimulationSettings.TargetTimeInterval * container.VehicleSpeed()).Cast<Meter>(); - - if (cnt++ % 100 == 0) { - modalWriter.Finish(); - } - } + response.Switch(). + Case<ResponseDrivingCycleDistanceExceeded>(r => ds = r.MaxDistance). + Case<ResponseCycleFinished>(r => { }). + Case<ResponseSuccess>(r => { + container.CommitSimulationStep(absTime, r.SimulationInterval); + absTime += r.SimulationInterval; + + ds = container.VehicleSpeed().IsEqual(0) + ? Constants.SimulationSettings.DriveOffDistance + : (Constants.SimulationSettings.TargetTimeInterval * container.VehicleSpeed()).Cast<Meter>(); + + if (cnt++ % 100 == 0) { + modalWriter.Finish(); + } + }). + Default(r => Assert.Fail("Unexpected Response: {0}", r)); } Assert.IsInstanceOfType(response, typeof(ResponseCycleFinished)); modalWriter.Finish(); - //var run = new DistanceRun(vehicleContainer); - //run.Run(); } private static GearData CreateAxleGearData() diff --git a/VectoCoreTest/Integration/SimulationRuns/MinimalPowertrain.cs b/VectoCoreTest/Integration/SimulationRuns/MinimalPowertrain.cs index f966466bc147709040cb3bcf519342b9ee3d3766..73383b4cc9bbb0efe2c7e15918888f1e59e5e71b 100644 --- a/VectoCoreTest/Integration/SimulationRuns/MinimalPowertrain.cs +++ b/VectoCoreTest/Integration/SimulationRuns/MinimalPowertrain.cs @@ -61,7 +61,7 @@ namespace TUGraz.VectoCore.Tests.Integration.SimulationRuns var driverPort = driver.OutPort(); - gbx.CurrentGear = 1; + vehicleContainer.Gear = 1; var response = driverPort.Initialize(18.KMPHtoMeterPerSecond(), VectoMath.InclinationToAngle(2.842372037 / 100)); @@ -113,53 +113,40 @@ namespace TUGraz.VectoCore.Tests.Integration.SimulationRuns cyclePort.Initialize(); - gbx.CurrentGear = 0; + vehicleContainer.Gear = 0; var absTime = 0.SI<Second>(); - var response = cyclePort.Request(absTime, 1.SI<Meter>()); - + var ds = Constants.SimulationSettings.DriveOffDistance; + var response = cyclePort.Request(absTime, ds); Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); - vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval); absTime += response.SimulationInterval; - gbx.CurrentGear = 1; - var ds = Constants.SimulationSettings.DriveOffDistance; + vehicleContainer.Gear = 1; var cnt = 0; - var doRun = true; - while (doRun && vehicleContainer.Distance().Value() < 17000) { + while (!(response is ResponseCycleFinished) && vehicleContainer.Distance().Value() < 17000) { response = cyclePort.Request(absTime, ds); - - switch (response.ResponseType) { - case ResponseType.DrivingCycleDistanceExceeded: - var rsp = response as ResponseDrivingCycleDistanceExceeded; - ds = rsp.MaxDistance; - continue; - case ResponseType.CycleFinished: - doRun = false; - break; - } - if (doRun) { - Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); - - vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval); - absTime += response.SimulationInterval; - - ds = vehicleContainer.VehicleSpeed().IsEqual(0) - ? Constants.SimulationSettings.DriveOffDistance - : (Constants.SimulationSettings.TargetTimeInterval * vehicleContainer.VehicleSpeed()).Cast<Meter>(); - - if (cnt++ % 100 == 0) { - modalWriter.Finish(); - } - } + response.Switch(). + Case<ResponseDrivingCycleDistanceExceeded>(r => ds = r.MaxDistance). + Case<ResponseCycleFinished>(r => { }). + Case<ResponseSuccess>(r => { + vehicleContainer.CommitSimulationStep(absTime, r.SimulationInterval); + absTime += r.SimulationInterval; + + ds = vehicleContainer.VehicleSpeed().IsEqual(0) + ? Constants.SimulationSettings.DriveOffDistance + : (Constants.SimulationSettings.TargetTimeInterval * vehicleContainer.VehicleSpeed()).Cast<Meter>(); + + if (cnt++ % 100 == 0) { + modalWriter.Finish(); + } + }). + Default(r => Assert.Fail("Unexpected Response: {0}", r)); } Assert.IsInstanceOfType(response, typeof(ResponseCycleFinished)); modalWriter.Finish(); - //var run = new DistanceRun(vehicleContainer); - //run.Run(); } [TestMethod] @@ -194,33 +181,26 @@ namespace TUGraz.VectoCore.Tests.Integration.SimulationRuns cyclePort.Initialize(); - gbx.CurrentGear = 0; + vehicleContainer.Gear = 0; var absTime = 0.SI<Second>(); - gbx.CurrentGear = 1; - IResponse response; + vehicleContainer.Gear = 1; var ds = Constants.SimulationSettings.DriveOffDistance; while (vehicleContainer.Distance().Value() < 100) { - response = cyclePort.Request(absTime, ds); - - switch (response.ResponseType) { - case ResponseType.DrivingCycleDistanceExceeded: - var rsp = response as ResponseDrivingCycleDistanceExceeded; - ds = rsp.MaxDistance; - continue; - } - Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); - + var response = cyclePort.Request(absTime, ds); + response.Switch(). + Case<ResponseDrivingCycleDistanceExceeded>(r => ds = r.MaxDistance). + Case<ResponseSuccess>(r => { + vehicleContainer.CommitSimulationStep(absTime, r.SimulationInterval); + absTime += r.SimulationInterval; - vehicleContainer.CommitSimulationStep(absTime, response.SimulationInterval); - absTime += response.SimulationInterval; + ds = vehicleContainer.VehicleSpeed().IsEqual(0) + ? Constants.SimulationSettings.DriveOffDistance + : (Constants.SimulationSettings.TargetTimeInterval * vehicleContainer.VehicleSpeed()).Cast<Meter>(); - ds = vehicleContainer.VehicleSpeed().IsEqual(0) - ? Constants.SimulationSettings.DriveOffDistance - : (Constants.SimulationSettings.TargetTimeInterval * vehicleContainer.VehicleSpeed()).Cast<Meter>(); - - modalWriter.Finish(); + modalWriter.Finish(); + }); } modalWriter.Finish(); diff --git a/VectoCoreTest/Models/SimulationComponent/ClutchTest.cs b/VectoCoreTest/Models/SimulationComponent/ClutchTest.cs index 25d7e2d4be6f6c88a0f7492b311145fa60f1ee5d..581595538dd7fe63401c1b8520c4cd872253d1d4 100644 --- a/VectoCoreTest/Models/SimulationComponent/ClutchTest.cs +++ b/VectoCoreTest/Models/SimulationComponent/ClutchTest.cs @@ -32,7 +32,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent var clutchOutPort = clutch.OutPort(); //Test - Clutch slipping - gearbox.CurrentGear = 1; + vehicle.Gear = 1; clutchOutPort.Request(0.SI<Second>(), 0.SI<Second>(), 100.SI<NewtonMeter>(), 0.SI<PerSecond>()); @@ -45,14 +45,14 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent Assert.AreEqual(62.119969, outPort.AngularVelocity.Value(), 0.001); //Test - Clutch opened - gearbox.CurrentGear = 0; + vehicle.Gear = 0; clutchOutPort.Request(0.SI<Second>(), 0.SI<Second>(), 100.SI<NewtonMeter>(), 30.SI<PerSecond>()); Assert.AreEqual(0, outPort.Torque.Value(), 0.001); Assert.AreEqual(engineData.IdleSpeed.Value(), outPort.AngularVelocity.Value(), 0.001); //Test - Clutch closed - gearbox.CurrentGear = 1; + vehicle.Gear = 1; clutchOutPort.Request(0.SI<Second>(), 0.SI<Second>(), 100.SI<NewtonMeter>(), 80.SI<PerSecond>()); Assert.AreEqual(100.0, outPort.Torque.Value(), 0.001); diff --git a/VectoCoreTest/Models/SimulationComponent/DriverTest.cs b/VectoCoreTest/Models/SimulationComponent/DriverTest.cs index 2471823b9b7b6ae13da4c8ac6bd53ae2abc5a2d5..9df9b439d7aae89507573460970a5dae7168b6d4 100644 --- a/VectoCoreTest/Models/SimulationComponent/DriverTest.cs +++ b/VectoCoreTest/Models/SimulationComponent/DriverTest.cs @@ -55,7 +55,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent AddComponent(tmp, engine); var gbx = new MockGearbox(vehicleContainer); - gbx.CurrentGear = 1; + vehicleContainer.Gear = 1; var driverPort = driver.OutPort(); @@ -109,7 +109,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent AddComponent(tmp, engine); var gbx = new MockGearbox(vehicleContainer); - gbx.CurrentGear = 1; + vehicleContainer.Gear = 1; var driverPort = driver.OutPort(); @@ -164,7 +164,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent AddComponent(tmp, new CombustionEngine(vehicleContainer, engineData)); var gbx = new MockGearbox(vehicleContainer); - gbx.CurrentGear = 1; + vehicleContainer.Gear = 1; var driverPort = driver.OutPort(); diff --git a/VectoCoreTest/Models/SimulationComponent/GearboxTest.cs b/VectoCoreTest/Models/SimulationComponent/GearboxTest.cs index dc06b85a34ef5afc173681e4852f4b4065abf8f5..dcc17e92b6bfcf26bb76e6fbd5b188d1a13b83d9 100644 --- a/VectoCoreTest/Models/SimulationComponent/GearboxTest.cs +++ b/VectoCoreTest/Models/SimulationComponent/GearboxTest.cs @@ -80,7 +80,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent var response = gearbox.OutPort() .Request(0.SI<Second>(), 1.SI<Second>(), 1500.SI<NewtonMeter>() / 6.38, 700.SI<PerSecond>() * 6.38); - Assert.AreEqual(ResponseType.FailOverload, response.ResponseType); + Assert.IsInstanceOfType(response, typeof(ResponseGearboxOverload)); } [TestMethod] @@ -108,7 +108,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent var angularVelocity = exp.n.RPMtoRad() / ratio; var response = gearbox.OutPort().Request(0.SI<Second>(), 1.SI<Second>(), torque, angularVelocity); - Assert.IsInstanceOfType(response, typeof(ResponseFailOverload)); + Assert.IsInstanceOfType(response, typeof(ResponseGearboxOverload)); } var expectedCorrect = new[] { @@ -141,26 +141,26 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent // the first element 0.0 is just a placeholder for axlegear, not used in this test var expected = new[] { - new { gear = 1, t = 50, n = 800, loss = 10.108, responseType = ResponseType.Success }, - new { gear = 1, t = 2450, n = 800, loss = 58.11, responseType = ResponseType.FailOverload }, - new { gear = 1, t = -1000, n = 800, loss = 29.11, responseType = ResponseType.Success }, - new { gear = 1, t = 850, n = 800, loss = 26.11, responseType = ResponseType.Success }, - new { gear = 1, t = 850, n = 0, loss = 22.06, responseType = ResponseType.Success }, - new { gear = 1, t = 850, n = 200, loss = 23.07, responseType = ResponseType.FailOverload }, - new { gear = 2, t = 50, n = 800, loss = 10.108, responseType = ResponseType.Success }, - new { gear = 2, t = 2450, n = 800, loss = 58.11, responseType = ResponseType.GearShift }, - new { gear = 2, t = -1000, n = 800, loss = 29.11, responseType = ResponseType.Success }, - new { gear = 2, t = 850, n = 800, loss = 26.11, responseType = ResponseType.Success }, - new { gear = 2, t = 850, n = 0, loss = 22.06, responseType = ResponseType.Success }, - new { gear = 2, t = 850, n = 400, loss = 11.334, responseType = ResponseType.GearShift }, - new { gear = 2, t = 850, n = 2000, loss = 32.18, responseType = ResponseType.GearShift }, - new { gear = 7, t = -1000, n = 0, loss = 10.06, responseType = ResponseType.Success }, - new { gear = 7, t = -1000, n = 1200, loss = 16.132, responseType = ResponseType.Success }, - new { gear = 7, t = 850, n = 0, loss = 9.31, responseType = ResponseType.Success }, - new { gear = 7, t = 850, n = 1200, loss = 15.382, responseType = ResponseType.Success }, - new { gear = 7, t = 850, n = 2000, loss = 19.43, responseType = ResponseType.GearShift }, - new { gear = 7, t = 2450, n = 0, loss = 17.31, responseType = ResponseType.Success }, - new { gear = 7, t = 2450, n = 1200, loss = 23.382, responseType = ResponseType.FailOverload } + new { gear = 1, t = 50, n = 800, loss = 10.108, responseType = typeof(ResponseSuccess) }, + new { gear = 1, t = 2450, n = 800, loss = 58.11, responseType = typeof(ResponseGearboxOverload) }, + new { gear = 1, t = -1000, n = 800, loss = 29.11, responseType = typeof(ResponseSuccess) }, + new { gear = 1, t = 850, n = 800, loss = 26.11, responseType = typeof(ResponseSuccess) }, + new { gear = 1, t = 850, n = 0, loss = 22.06, responseType = typeof(ResponseSuccess) }, + new { gear = 1, t = 850, n = 200, loss = 23.07, responseType = typeof(ResponseGearboxOverload) }, + new { gear = 2, t = 50, n = 800, loss = 10.108, responseType = typeof(ResponseSuccess) }, + new { gear = 2, t = 2450, n = 800, loss = 58.11, responseType = typeof(ResponseGearShift) }, + new { gear = 2, t = -1000, n = 800, loss = 29.11, responseType = typeof(ResponseSuccess) }, + new { gear = 2, t = 850, n = 800, loss = 26.11, responseType = typeof(ResponseSuccess) }, + new { gear = 2, t = 850, n = 0, loss = 22.06, responseType = typeof(ResponseSuccess) }, + new { gear = 2, t = 850, n = 400, loss = 11.334, responseType = typeof(ResponseGearShift) }, + new { gear = 2, t = 850, n = 2000, loss = 32.18, responseType = typeof(ResponseGearShift) }, + new { gear = 7, t = -1000, n = 0, loss = 10.06, responseType = typeof(ResponseSuccess) }, + new { gear = 7, t = -1000, n = 1200, loss = 16.132, responseType = typeof(ResponseSuccess) }, + new { gear = 7, t = 850, n = 0, loss = 9.31, responseType = typeof(ResponseSuccess) }, + new { gear = 7, t = 850, n = 1200, loss = 15.382, responseType = typeof(ResponseSuccess) }, + new { gear = 7, t = 850, n = 2000, loss = 19.43, responseType = typeof(ResponseGearShift) }, + new { gear = 7, t = 2450, n = 0, loss = 17.31, responseType = typeof(ResponseSuccess) }, + new { gear = 7, t = 2450, n = 1200, loss = 23.382, responseType = typeof(ResponseGearboxOverload) } }; var absTime = 0.SI<Second>(); @@ -176,13 +176,13 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent container.Gear = (uint)exp.gear; var response = gearbox.OutPort().Request(absTime, dt, torque, angularVelocity); - Assert.AreEqual(exp.responseType, response.ResponseType, exp.ToString()); + Assert.IsInstanceOfType(response, exp.responseType, exp.ToString()); if (angularVelocity.IsEqual(0)) { expectedT = 0.SI<NewtonMeter>(); } - if (exp.responseType == ResponseType.Success) { + if (exp.responseType == typeof(ResponseSuccess)) { AssertHelper.AreRelativeEqual(absTime, port.AbsTime, message: exp.ToString()); AssertHelper.AreRelativeEqual(dt, port.Dt, message: exp.ToString()); AssertHelper.AreRelativeEqual(expectedN, port.AngularVelocity, message: exp.ToString()); @@ -207,15 +207,15 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent // the first element 0.0 is just a placeholder for axlegear, not used in this test var expected = new[] { - new { gear = 8, newGear = 7, t = 1500, n = 700, responseType = ResponseType.GearShift }, - new { gear = 7, newGear = 6, t = 1500, n = 700, responseType = ResponseType.GearShift }, - new { gear = 6, newGear = 5, t = 1500, n = 700, responseType = ResponseType.GearShift }, - new { gear = 5, newGear = 4, t = 1500, n = 700, responseType = ResponseType.GearShift }, - new { gear = 4, newGear = 3, t = 1500, n = 700, responseType = ResponseType.GearShift }, - new { gear = 3, newGear = 2, t = 1500, n = 700, responseType = ResponseType.GearShift }, - new { gear = 2, newGear = 1, t = 1500, n = 700, responseType = ResponseType.GearShift }, - new { gear = 1, newGear = 1, t = 1200, n = 700, responseType = ResponseType.Success }, - new { gear = 8, newGear = 1, t = 10000, n = 120, responseType = ResponseType.GearShift } + new { gear = 8, newGear = 7, t = 1500, n = 700, responseType = typeof(ResponseGearShift) }, + new { gear = 7, newGear = 6, t = 1500, n = 700, responseType = typeof(ResponseGearShift) }, + new { gear = 6, newGear = 5, t = 1500, n = 700, responseType = typeof(ResponseGearShift) }, + new { gear = 5, newGear = 4, t = 1500, n = 700, responseType = typeof(ResponseGearShift) }, + new { gear = 4, newGear = 3, t = 1500, n = 700, responseType = typeof(ResponseGearShift) }, + new { gear = 3, newGear = 2, t = 1500, n = 700, responseType = typeof(ResponseGearShift) }, + new { gear = 2, newGear = 1, t = 1500, n = 700, responseType = typeof(ResponseGearShift) }, + new { gear = 1, newGear = 1, t = 1200, n = 700, responseType = typeof(ResponseSuccess) }, + new { gear = 8, newGear = 1, t = 10000, n = 120, responseType = typeof(ResponseGearShift) } }; var absTime = 0.SI<Second>(); @@ -230,7 +230,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent container.Gear = (uint)exp.gear; var response = gearbox.OutPort().Request(absTime, dt, torque, angularVelocity); - Assert.AreEqual(exp.responseType, response.ResponseType, exp.ToString()); + Assert.IsInstanceOfType(response, exp.responseType, exp.ToString()); Assert.AreEqual((uint)exp.newGear, container.Gear, exp.ToString()); absTime += dt; } @@ -250,15 +250,15 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent // the first element 0.0 is just a placeholder for axlegear, not used in this test var expected = new[] { - new { gear = 7, newGear = 8, t = 1000, n = 1400, responseType = ResponseType.GearShift }, - new { gear = 6, newGear = 7, t = 1000, n = 1400, responseType = ResponseType.GearShift }, - new { gear = 5, newGear = 6, t = 1000, n = 1400, responseType = ResponseType.GearShift }, - new { gear = 4, newGear = 5, t = 1000, n = 1400, responseType = ResponseType.GearShift }, - new { gear = 3, newGear = 4, t = 1000, n = 1400, responseType = ResponseType.GearShift }, - new { gear = 2, newGear = 3, t = 1000, n = 1400, responseType = ResponseType.GearShift }, - new { gear = 1, newGear = 2, t = 1000, n = 1400, responseType = ResponseType.GearShift }, - new { gear = 8, newGear = 8, t = 1000, n = 1400, responseType = ResponseType.Success }, - new { gear = 1, newGear = 8, t = 200, n = 9000, responseType = ResponseType.GearShift } + new { gear = 7, newGear = 8, t = 1000, n = 1400, responseType = typeof(ResponseGearShift) }, + new { gear = 6, newGear = 7, t = 1000, n = 1400, responseType = typeof(ResponseGearShift) }, + new { gear = 5, newGear = 6, t = 1000, n = 1400, responseType = typeof(ResponseGearShift) }, + new { gear = 4, newGear = 5, t = 1000, n = 1400, responseType = typeof(ResponseGearShift) }, + new { gear = 3, newGear = 4, t = 1000, n = 1400, responseType = typeof(ResponseGearShift) }, + new { gear = 2, newGear = 3, t = 1000, n = 1400, responseType = typeof(ResponseGearShift) }, + new { gear = 1, newGear = 2, t = 1000, n = 1400, responseType = typeof(ResponseGearShift) }, + new { gear = 8, newGear = 8, t = 1000, n = 1400, responseType = typeof(ResponseSuccess) }, + new { gear = 1, newGear = 8, t = 200, n = 9000, responseType = typeof(ResponseGearShift) } }; var absTime = 0.SI<Second>(); @@ -273,7 +273,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent container.Gear = (uint)exp.gear; var response = gearbox.OutPort().Request(absTime, dt, torque, angularVelocity); - Assert.AreEqual(exp.responseType, response.ResponseType, exp.ToString()); + Assert.IsInstanceOfType(response, exp.responseType, exp.ToString()); Assert.AreEqual((uint)exp.newGear, container.Gear, exp.ToString()); absTime += dt; } @@ -292,7 +292,7 @@ namespace TUGraz.VectoCore.Tests.Models.SimulationComponent container.Gear = 0; var response = gearbox.OutPort() .Request(0.SI<Second>(), 1.SI<Second>(), 50000000.SI<NewtonMeter>(), 1000000.SI<PerSecond>()); - Assert.AreEqual(response.ResponseType, ResponseType.Success); + Assert.IsInstanceOfType(response, typeof(ResponseSuccess)); AssertHelper.AreRelativeEqual(0.SI<Second>(), port.AbsTime); AssertHelper.AreRelativeEqual(1.SI<Second>(), port.Dt); diff --git a/VectoCoreTest/Utils/MockGearbox.cs b/VectoCoreTest/Utils/MockGearbox.cs index f16106ab05ba540abb7b4e9b432bc0a8cbf7dce2..a6959cdb825f05fcd7f604c2837d618ed81023c3 100644 --- a/VectoCoreTest/Utils/MockGearbox.cs +++ b/VectoCoreTest/Utils/MockGearbox.cs @@ -10,8 +10,6 @@ namespace TUGraz.VectoCore.Tests.Utils public class MockGearbox : VectoSimulationComponent, IGearbox, ITnInPort, ITnOutPort { private ITnOutPort _outPort; - public uint CurrentGear { get; set; } - public MockGearbox(IVehicleContainer cockpit) : base(cockpit) {} @@ -25,11 +23,7 @@ namespace TUGraz.VectoCore.Tests.Utils return this; } - public uint Gear - { - get { return CurrentGear; } - set { CurrentGear = value; } - } + public uint Gear { get; set; } public void Connect(ITnOutPort other)