diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/ATGearbox.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/ATGearbox.cs index 674a8bcdeab3b4d6d27d9c2fa30c92c04cf48477..586f2a494c275ab9a82e770dd6da16912d4ccf86 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/ATGearbox.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/ATGearbox.cs @@ -230,14 +230,15 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl } response = TorqueConverter.Initialize(inTorque, inAngularVelocity); } - - response.Switch(). - Case<ResponseSuccess>(). // accept - Case<ResponseUnderload>(). // accept - Case<ResponseOverload>(). // accept - Default(r => { - throw new UnexpectedResponseException("AT-Gearbox.Initialize", r); - }); + + switch (response) { + case ResponseSuccess _: + case ResponseUnderload _: + case ResponseOverload _: + break; + default: + throw new UnexpectedResponseException("AT-Gearbox.Initialize", response); + } return new ResponseDryRun(this) { Engine = { diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs index fd4d86c13873aa0c53d4b5a34c27da1005453bfe..3eb8529f93e1a4111b0cc3dcf76a8b985a0a84ef 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/CombustionEngine.cs @@ -735,35 +735,37 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl var retVal = RequestPort.Request(absTime, dt, 0.SI<NewtonMeter>(), nextAngularSpeed, false); - retVal.Switch(). - Case<ResponseSuccess>(). - Case<ResponseUnderload>(r => { + switch(retVal) { + case ResponseSuccess _: + break; + case ResponseUnderload r: var angularSpeed = SearchAlgorithm.Search(nextAngularSpeed, r.Delta, Constants.SimulationSettings.EngineIdlingSearchInterval, getYValue: result => ((ResponseDryRun)result).DeltaDragLoad, evaluateFunction: n => RequestPort.Request(absTime, dt, 0.SI<NewtonMeter>(), n, true), criterion: result => ((ResponseDryRun)result).DeltaDragLoad.Value()); - Log.Debug("Found operating point for idling. absTime: {0}, dt: {1}, torque: {2}, angularSpeed: {3}", absTime, dt, - 0.SI<NewtonMeter>(), angularSpeed); + Log.Debug("Found operating point for idling. absTime: {0}, dt: {1}, torque: {2}, angularSpeed: {3}", + absTime, dt, 0.SI<NewtonMeter>(), angularSpeed); if (angularSpeed < _engine.ModelData.IdleSpeed) { angularSpeed = _engine.ModelData.IdleSpeed; } retVal = RequestPort.Request(absTime, dt, 0.SI<NewtonMeter>(), angularSpeed, false); - }). - Case<ResponseOverload>(r => { - var angularSpeed = SearchAlgorithm.Search(nextAngularSpeed, r.Delta, + break; + case ResponseOverload r: + var angularSpeed2 = SearchAlgorithm.Search(nextAngularSpeed, r.Delta, Constants.SimulationSettings.EngineIdlingSearchInterval, getYValue: result => ((ResponseDryRun)result).DeltaFullLoad, evaluateFunction: n => RequestPort.Request(absTime, dt, 0.SI<NewtonMeter>(), n, true), criterion: result => ((ResponseDryRun)result).DeltaFullLoad.Value()); - Log.Debug("Found operating point for idling. absTime: {0}, dt: {1}, torque: {2}, angularSpeed: {3}", absTime, dt, - 0.SI<NewtonMeter>(), angularSpeed); - angularSpeed = angularSpeed.LimitTo(_engine.ModelData.IdleSpeed, engineMaxSpeed); - retVal = RequestPort.Request(absTime, dt, 0.SI<NewtonMeter>(), angularSpeed, false); - }). - Default(r => { throw new UnexpectedResponseException("searching Idling point", r); }); - + Log.Debug("Found operating point for idling. absTime: {0}, dt: {1}, torque: {2}, angularSpeed: {3}", + absTime, dt, 0.SI<NewtonMeter>(), angularSpeed2); + angularSpeed2 = angularSpeed2.LimitTo(_engine.ModelData.IdleSpeed, engineMaxSpeed); + retVal = RequestPort.Request(absTime, dt, 0.SI<NewtonMeter>(), angularSpeed2, false); + break; + default: + throw new UnexpectedResponseException("searching Idling point", retVal); + } return retVal; } @@ -802,20 +804,22 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl .LimitTo(_engine.ModelData.IdleSpeed, _engine.EngineRatedSpeed); retVal = RequestPort.Request(absTime, dt, 0.SI<NewtonMeter>(), nextAngularSpeed, false); - retVal.Switch(). - Case<ResponseSuccess>(). - Case<ResponseUnderload>(r => { + switch (retVal) { + case ResponseSuccess _: + break; + case ResponseUnderload r: var angularSpeed = SearchAlgorithm.Search(nextAngularSpeed, r.Delta, Constants.SimulationSettings.EngineIdlingSearchInterval, getYValue: result => ((ResponseDryRun)result).DeltaDragLoad, evaluateFunction: n => RequestPort.Request(absTime, dt, 0.SI<NewtonMeter>(), n, true), criterion: result => ((ResponseDryRun)result).DeltaDragLoad.Value()); - Log.Debug("Found operating point for idling. absTime: {0}, dt: {1}, torque: {2}, angularSpeed: {3}", absTime, dt, - 0.SI<NewtonMeter>(), angularSpeed); + Log.Debug("Found operating point for idling. absTime: {0}, dt: {1}, torque: {2}, angularSpeed: {3}", + absTime, dt, 0.SI<NewtonMeter>(), angularSpeed); retVal = RequestPort.Request(absTime, dt, 0.SI<NewtonMeter>(), angularSpeed, false); - }). - Default(r => { throw new UnexpectedResponseException("searching Idling point", r); }); - + break; + default: + throw new UnexpectedResponseException("searching Idling point", retVal); + } return retVal; } } diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/DefaultDriverStrategy.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/DefaultDriverStrategy.cs index 3d9f71a01e5c9bfc037fc6d6dc1805fc933b9c8c..7ab325a3f5756cdd303e7f8cd503e7d1d7e10abf 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/DefaultDriverStrategy.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/DefaultDriverStrategy.cs @@ -33,6 +33,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Windows.Forms.DataVisualization.Charting; using TUGraz.VectoCommon.Exceptions; using TUGraz.VectoCommon.InputData; using TUGraz.VectoCommon.Models; @@ -204,13 +205,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl //if (ADAS.EcoRoll != EcoRollType.None) { // todo MQ: keep something like this to prevent driver to turn on engine in every timestep (in combination with hybrids leads to errors!) - if (EcoRollState.State != EcoRollStates.EcoRollOn && PCCState != PCCStates.UseCase1 && - PCCState != PCCStates.UseCase2) { - EngineOffTimestamp = null; - if (Driver.DataBus.PowertrainInfo.HasCombustionEngine && !Driver.DataBus.PowertrainInfo.HasElectricMotor) { - Driver.DataBus.EngineCtl.CombustionEngineOn = true; - } + if (EcoRollState.State != EcoRollStates.EcoRollOn && PCCState != PCCStates.UseCase1 && + PCCState != PCCStates.UseCase2) { + EngineOffTimestamp = null; + if (Driver.DataBus.PowertrainInfo.HasCombustionEngine && !Driver.DataBus.PowertrainInfo.HasElectricMotor) { + Driver.DataBus.EngineCtl.CombustionEngineOn = true; } + } //} if (CurrentDrivingMode == DrivingMode.DrivingModeBrake) { @@ -224,7 +225,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl DrivingModes[CurrentDrivingMode].ResetMode(); Log.Debug("Switching to DrivingMode DRIVE"); } - + } if (CurrentDrivingMode == DrivingMode.DrivingModeDrive) { @@ -250,8 +251,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl .IsSmaller( Constants.SimulationSettings.LowerBoundTimeInterval / 2) && (Driver.DataBus.GearboxInfo.GearboxType.AutomaticTransmission() || !Driver.DataBus.ClutchInfo.ClutchClosed(absTime)); if (brakingIntervalShort && remainingDistance.IsEqual(ds)) { - return new ResponseDrivingCycleDistanceExceeded(this) - { + return new ResponseDrivingCycleDistanceExceeded(this) { MaxDistance = ds / 2 }; } @@ -594,7 +594,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { return (targetSpeed + GetOverspeed()).LimitTo( 0.KMPHtoMeterPerSecond(), VehicleCategory.IsBus() ? Constants.BusParameters.MaxBusSpeed : 500.KMPHtoMeterPerSecond()); - + } protected internal MeterPerSecond GetOverspeed() @@ -871,12 +871,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl if (DriverStrategy.OverspeedAllowed(targetVelocity, prohibitOverspeed)) { velocity = DriverStrategy.ApplyOverspeed(velocity); } - - if (DataBus.GearboxInfo.GearboxType.AutomaticTransmission() || (DataBus.ClutchInfo.ClutchClosed(absTime) && DataBus.GearboxInfo.GearEngaged(absTime) )) { - if (DataBus.DrivingCycleInfo.CycleData.LeftSample.PTOActive == PTOActivity.PTOActivityRoadSweeping && targetVelocity < DriverStrategy.PTODriveMinSpeed) { - velocity = DriverStrategy.PTODriveMinSpeed; - targetVelocity = velocity; - } + + if (DataBus.GearboxInfo.GearboxType.AutomaticTransmission() || (DataBus.ClutchInfo.ClutchClosed(absTime) && DataBus.GearboxInfo.GearEngaged(absTime))) { + if (DataBus.DrivingCycleInfo.CycleData.LeftSample.PTOActive == PTOActivity.PTOActivityRoadSweeping && targetVelocity < DriverStrategy.PTODriveMinSpeed) { + velocity = DriverStrategy.PTODriveMinSpeed; + targetVelocity = velocity; + } for (var i = 0; i < 3; i++) { var retVal = HandleRequestEngaged( @@ -920,20 +920,19 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl var response = Driver.DrivingActionRoll(absTime, ds, velocity, gradient); debug.Add(new { action = "ClutchOpen -> Roll", response }); - response.Switch().Case<ResponseUnderload>( - r => { - if (DataBus.ClutchInfo.ClutchClosed(absTime)) { - response = HandleRequestEngaged(absTime, ds, velocity, gradient, false, velocity, debug); - } else { - response = Driver.DrivingActionBrake(absTime, ds, velocity, gradient, r); - debug.Add(new { action = "Roll:Underload -> Brake", response }); - } - }) - .Case<ResponseSpeedLimitExceeded>( - () => { - response = Driver.DrivingActionBrake(absTime, ds, velocity, gradient); - debug.Add(new { action = "Roll:SpeedLimitExceeded -> Brake", response }); - }); + switch (response) { + case ResponseUnderload _ when DataBus.ClutchInfo.ClutchClosed(absTime): + response = HandleRequestEngaged(absTime, ds, velocity, gradient, false, velocity, debug); + break; + case ResponseUnderload _ when !DataBus.ClutchInfo.ClutchClosed(absTime): + response = Driver.DrivingActionBrake(absTime, ds, velocity, gradient, response); + debug.Add(new { action = "Roll:Underload -> Brake", response }); + break; + case ResponseSpeedLimitExceeded _: + response = Driver.DrivingActionBrake(absTime, ds, velocity, gradient); + debug.Add(new { action = "Roll:SpeedLimitExceeded -> Brake", response }); + break; + } return response; } @@ -946,32 +945,33 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl absTime, ds, targetVelocity, gradient, prohibitOverspeed, velocityWithOverspeed, debug); var second = first; - first.Switch() - .Case<ResponseUnderload>( - r => { - if (DataBus.GearboxInfo.GearboxType.AutomaticTransmission() && !DataBus.ClutchInfo.ClutchClosed(absTime)) { - second = Driver.DrivingActionRoll(absTime, ds, velocityWithOverspeed, gradient); - } - if (DataBus.VehicleInfo.VehicleSpeed.IsGreater(0) && DriverStrategy.OverspeedAllowed(targetVelocity, prohibitOverspeed)) { - second = Driver.DrivingActionCoast(absTime, ds, velocityWithOverspeed, gradient); - debug.Add(new { action = "first:(Underload & Overspeed)-> Coast", second }); - second = HandleCoastAfterUnderloadWithOverspeed(absTime, ds, gradient, velocityWithOverspeed, debug, second); - } else { - second = Driver.DrivingActionBrake(absTime, ds, velocityWithOverspeed, gradient, - overrideAction: DataBus.GearboxInfo.GearboxType.AutomaticTransmission() - ? DrivingAction.Accelerate - : (DrivingAction?)null); - debug.Add(new { action = "first:(Underload & !Overspeed) -> Brake", second }); - } - }) - .Case<ResponseEngineSpeedTooHigh>( - r => { second = Driver.DrivingActionBrake(absTime, ds, targetVelocity, gradient, r); }) - .Case<ResponseSpeedLimitExceeded>( - r => { - second = Driver.DrivingActionBrake(absTime, ds, velocityWithOverspeed, gradient); - debug.Add(new { action = "SpeedLimitExceeded -> Brake", second }); - }); - ; + switch (first) { + case ResponseUnderload _: + if (DataBus.GearboxInfo.GearboxType.AutomaticTransmission() && !DataBus.ClutchInfo.ClutchClosed(absTime)) { + //TODO mk20210616 the assignment to second is always overriden. Delete the assignment, or maybe even delete the whole line? + //TODO mk20210616 the whole statement could be de-nested to switch-pattern matching (with "where") if this first "if" would not be here. + second = Driver.DrivingActionRoll(absTime, ds, velocityWithOverspeed, gradient); + } + + if (DataBus.VehicleInfo.VehicleSpeed.IsGreater(0) && DriverStrategy.OverspeedAllowed(targetVelocity, prohibitOverspeed)) { + second = Driver.DrivingActionCoast(absTime, ds, velocityWithOverspeed, gradient); + debug.Add(new { action = "first:(Underload & Overspeed)-> Coast", second }); + second = HandleCoastAfterUnderloadWithOverspeed(absTime, ds, gradient, velocityWithOverspeed, debug, second); + } else { + second = DataBus.GearboxInfo.GearboxType.AutomaticTransmission() + ? Driver.DrivingActionBrake(absTime, ds, velocityWithOverspeed, gradient, overrideAction: DrivingAction.Accelerate) + : Driver.DrivingActionBrake(absTime, ds, velocityWithOverspeed, gradient); + debug.Add(new { action = "first:(Underload & !Overspeed) -> Brake", second }); + } + break; + case ResponseEngineSpeedTooHigh _: + second = Driver.DrivingActionBrake(absTime, ds, targetVelocity, gradient, first); + break; + case ResponseSpeedLimitExceeded _: + second = Driver.DrivingActionBrake(absTime, ds, velocityWithOverspeed, gradient); + debug.Add(new { action = "SpeedLimitExceeded -> Brake", second }); + break; + } if (second == null) { return null; @@ -979,27 +979,27 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl var third = second; - second.Switch().Case<ResponseGearShift>( - r => { + switch (second) { + case ResponseGearShift _: third = Driver.DrivingActionRoll(absTime, ds, velocityWithOverspeed, gradient); debug.Add(new { action = "second: GearShift -> Roll", third }); - third.Switch().Case<ResponseUnderload>( - () => { + switch (third) { + case ResponseUnderload _: // overload may happen if driver limits acceleration when rolling downhill third = Driver.DrivingActionBrake(absTime, ds, velocityWithOverspeed, gradient); debug.Add(new { action = "third:Underload -> Brake", third }); - }).Case<ResponseSpeedLimitExceeded>( - () => { + break; + case ResponseSpeedLimitExceeded _: third = Driver.DrivingActionBrake(absTime, ds, velocityWithOverspeed, gradient); debug.Add(new { action = "third:SpeedLimitExceeded -> Brake", third }); - }); - }).Case<ResponseOverload>( - r => { - if (DataBus.VehicleInfo.VehicleSpeed.IsGreater(0)) { - third = Driver.DrivingActionCoast(absTime, ds, velocityWithOverspeed, gradient); - debug.Add(new { action = "second:Overload -> Coast", third }); + break; } - }); + break; + case ResponseOverload _ when DataBus.VehicleInfo.VehicleSpeed.IsGreater(0): + third = Driver.DrivingActionCoast(absTime, ds, velocityWithOverspeed, gradient); + debug.Add(new { action = "second:Overload -> Coast", third }); + break; + } return third; } @@ -1229,126 +1229,114 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl } } - response.Switch().Case<ResponseOverload>( - r => { - Log.Info( - "Brake -> Got OverloadResponse during brake action - desired deceleration could not be reached! response: {0}", - r); + switch (response) { + case ResponseOverload r: + Log.Info("Brake -> Got OverloadResponse during brake action - desired deceleration could not be reached! response: {0}", r); if (!DataBus.ClutchInfo.ClutchClosed(absTime)) { Log.Info("Brake -> Overload -> Clutch is open - Trying roll action"); response = Driver.DrivingActionRoll(absTime, ds, targetVelocity, gradient); - response.Switch().Case<ResponseSpeedLimitExceeded>( - () => { response = Driver.DrivingActionBrake(absTime, ds, targetVelocity, gradient); } - ); + if (response is ResponseSpeedLimitExceeded) + response = Driver.DrivingActionBrake(absTime, ds, targetVelocity, gradient); } else { Log.Info("Brake -> Overload -> Clutch is closed - Trying brake action again"); DataBus.Brakes.BrakePower = 0.SI<Watt>(); DataBus.HybridControllerCtl?.RepeatDrivingAction(absTime); - response = Driver.DrivingActionBrake( - absTime, ds, DriverStrategy.BrakeTrigger.NextTargetSpeed, gradient, - targetDistance: targetDistance); - response.Switch().Case<ResponseOverload>( - r1 => { - Log.Info("Brake -> Overload -> 2nd Brake -> Overload -> Trying accelerate action"); - var gear = DataBus.GearboxInfo.Gear; - if (DataBus.GearboxInfo.GearEngaged(absTime)) { - response = Driver.DrivingActionAccelerate( - absTime, ds, DriverStrategy.BrakeTrigger.NextTargetSpeed, gradient); - } else { - response = Driver.DrivingActionRoll(absTime, ds, targetVelocity, gradient); - } - - response.Switch().Case<ResponseGearShift>( - rs => { - Log.Info( - "Brake -> Overload -> 2nd Brake -> Accelerate -> Got GearShift response, performing roll action"); - response = Driver.DrivingActionRoll(absTime, ds, DriverStrategy.BrakeTrigger.NextTargetSpeed, gradient); - }) - .Case<ResponseUnderload>( - rs => { - if (gear != DataBus.GearboxInfo.Gear) { - // AT Gearbox switched gears, shift losses are no longer applied, try once more... - response = Driver.DrivingActionAccelerate(absTime, ds, DriverStrategy.BrakeTrigger.NextTargetSpeed, gradient); - } - }); - }); + response = Driver.DrivingActionBrake(absTime, ds, DriverStrategy.BrakeTrigger.NextTargetSpeed, + gradient, targetDistance: targetDistance); + if (response is ResponseOverload) { + Log.Info("Brake -> Overload -> 2nd Brake -> Overload -> Trying accelerate action"); + var gear = DataBus.GearboxInfo.Gear; + response = DataBus.GearboxInfo.GearEngaged(absTime) + ? Driver.DrivingActionAccelerate(absTime, ds, DriverStrategy.BrakeTrigger.NextTargetSpeed, gradient) + : Driver.DrivingActionRoll(absTime, ds, targetVelocity, gradient); + + switch (response) { + case ResponseGearShift _: + Log.Info("Brake -> Overload -> 2nd Brake -> Accelerate -> Got GearShift response, performing roll action"); + response = Driver.DrivingActionRoll(absTime, ds, + DriverStrategy.BrakeTrigger.NextTargetSpeed, gradient); + break; + case ResponseUnderload _: + if (gear.Gear != DataBus.GearboxInfo.Gear.Gear) { + // AT Gearbox switched gears, shift losses are no longer applied, try once more... + response = Driver.DrivingActionAccelerate(absTime, ds, + DriverStrategy.BrakeTrigger.NextTargetSpeed, gradient); + } + break; + } + } } - }).Case<ResponseGearShift>( - r => { + break; + case ResponseGearShift _: Log.Info("Brake -> Got GearShift response, performing roll action + brakes"); //response = Driver.DrivingActionRoll(absTime, ds, DriverStrategy.BrakeTrigger.NextTargetSpeed, gradient); DataBus.Brakes.BrakePower = 0.SI<Watt>(); - response = Driver.DrivingActionBrake( - absTime, ds, DriverStrategy.BrakeTrigger.NextTargetSpeed, + response = Driver.DrivingActionBrake(absTime, ds, DriverStrategy.BrakeTrigger.NextTargetSpeed, gradient, targetDistance: targetDistance); - response.Switch().Case<ResponseOverload>( - () => { - Log.Info("Brake -> Geearshift -> Overload -> trying roll action (no gear engaged)"); - response = Driver.DrivingActionRoll(absTime, ds, DriverStrategy.BrakeTrigger.NextTargetSpeed, gradient); - }); - }); + if (response is ResponseOverload) { + Log.Info("Brake -> Gearshift -> Overload -> trying roll action (no gear engaged)"); + response = Driver.DrivingActionRoll(absTime, ds, DriverStrategy.BrakeTrigger.NextTargetSpeed, gradient); + } + break; + } return response; } - private IResponse DoCoast( - Second absTime, Meter ds, MeterPerSecond targetVelocity, Radian gradient, - Meter currentDistance) + private IResponse DoCoast(Second absTime, Meter ds, MeterPerSecond targetVelocity, Radian gradient, Meter currentDistance) { IResponse response; Driver.DriverBehavior = DrivingBehavior.Coasting; response = DataBus.ClutchInfo.ClutchClosed(absTime) ? Driver.DrivingActionCoast(absTime, ds, VectoMath.Max(targetVelocity, DataBus.VehicleInfo.VehicleSpeed), gradient) : Driver.DrivingActionRoll(absTime, ds, VectoMath.Max(targetVelocity, DataBus.VehicleInfo.VehicleSpeed), gradient); - response.Switch().Case<ResponseUnderload>( - r => { + switch (response) { + case ResponseUnderload r: // coast would decelerate more than driver's max deceleration => issue brakes to decelerate with driver's max deceleration - response = Driver.DrivingActionBrake( - absTime, ds, DriverStrategy.BrakeTrigger.NextTargetSpeed, - gradient, r); - if ((DriverStrategy.BrakeTrigger.BrakingStartDistance - currentDistance).IsSmallerOrEqual( - Constants.SimulationSettings.DriverActionDistanceTolerance)) { + response = Driver.DrivingActionBrake(absTime, ds, DriverStrategy.BrakeTrigger.NextTargetSpeed, gradient, r); + if ((DriverStrategy.BrakeTrigger.BrakingStartDistance - currentDistance).IsSmallerOrEqual(Constants.SimulationSettings.DriverActionDistanceTolerance)) { Phase = BrakingPhase.Brake; } - }).Case<ResponseOverload>( - r => { + break; + case ResponseOverload _: // limiting deceleration while coast may result in an overload => issue brakes to decelerate with driver's max deceleration response = DataBus.ClutchInfo.ClutchClosed(absTime) ? Driver.DrivingActionAccelerate(absTime, ds, targetVelocity, gradient) : Driver.DrivingActionRoll(absTime, ds, targetVelocity, gradient); - //Phase = BrakingPhase.Brake; - }).Case<ResponseDrivingCycleDistanceExceeded>( - r => { + break; + case ResponseDrivingCycleDistanceExceeded r: if (!ds.IsEqual(r.MaxDistance)) { // distance has been reduced due to vehicle stop in coast/roll action => use brake action to get exactly to the stop-distance // TODO what if no gear is enaged (and we need driveline power to get to the stop-distance? response = Driver.DrivingActionBrake(absTime, ds, DriverStrategy.BrakeTrigger.NextTargetSpeed, gradient); } - }).Case<ResponseEngineSpeedTooHigh>( - r => { response = Driver.DrivingActionBrake(absTime, ds, targetVelocity, gradient, r); }); + break; + case ResponseEngineSpeedTooHigh r: + response = Driver.DrivingActionBrake(absTime, ds, targetVelocity, gradient, r); + break; + } + if (response == null) { - return response; + return null; } // handle the SpeedLimitExceeded Response and Gearshift Response separately in case it occurs in one of the requests in the second try for (var i = 0; i < 3 && (response is ResponseGearShift || response is ResponseSpeedLimitExceeded); i++) { - response.Switch() - .Case<ResponseGearShift>( - r => { response = Driver.DrivingActionRoll(absTime, ds, targetVelocity, gradient); }) - .Case<ResponseSpeedLimitExceeded>( - () => { - response = Driver.DrivingActionBrake( - absTime, ds, DataBus.VehicleInfo.VehicleSpeed, - gradient); - if (response is ResponseOverload && !DataBus.ClutchInfo.ClutchClosed(absTime)) { - response = Driver.DrivingActionRoll(absTime, ds, DataBus.VehicleInfo.VehicleSpeed, gradient); - } - if (response is ResponseGearShift) { - response = Driver.DrivingActionBrake(absTime, ds, DataBus.VehicleInfo.VehicleSpeed, - gradient); - } - }); + switch (response) { + case ResponseGearShift _: + response = Driver.DrivingActionRoll(absTime, ds, targetVelocity, gradient); + break; + case ResponseSpeedLimitExceeded _: + response = Driver.DrivingActionBrake(absTime, ds, DataBus.VehicleInfo.VehicleSpeed, gradient); + if (response is ResponseOverload && !DataBus.ClutchInfo.ClutchClosed(absTime)) { + response = Driver.DrivingActionRoll(absTime, ds, DataBus.VehicleInfo.VehicleSpeed, gradient); + } + if (response is ResponseGearShift) { + response = Driver.DrivingActionBrake(absTime, ds, DataBus.VehicleInfo.VehicleSpeed, gradient); + } + break; + } } return response; @@ -1397,51 +1385,46 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl //var i = 0; //do { - response.Switch().Case<ResponseGearShift>( - () => { + switch (response) { + case ResponseGearShift _: response = Driver.DrivingActionRoll(absTime, ds, targetVelocity, gradient); - response.Switch().Case<ResponseUnderload>( - r => { + switch (response) { + case ResponseUnderload r: // under-load may happen if driver limits acceleration when rolling downhill - response = Driver.DrivingActionBrake( - absTime, ds, DriverStrategy.BrakeTrigger.NextTargetSpeed, - gradient, r); - }).Case<ResponseSpeedLimitExceeded>( - () => { - response = Driver.DrivingActionBrake( - absTime, ds, DataBus.VehicleInfo.VehicleSpeed, - gradient); - }); - }).Case<ResponseSpeedLimitExceeded>( - () => { - response = Driver.DrivingActionBrake( - absTime, ds, DataBus.VehicleInfo.VehicleSpeed, - gradient); - }).Case<ResponseUnderload>( - r => { + response = Driver.DrivingActionBrake(absTime, ds, DriverStrategy.BrakeTrigger.NextTargetSpeed, gradient, r); + break; + case ResponseSpeedLimitExceeded _: + response = Driver.DrivingActionBrake(absTime, ds, DataBus.VehicleInfo.VehicleSpeed, gradient); + break; + } + break; + case ResponseSpeedLimitExceeded _: + response = Driver.DrivingActionBrake(absTime, ds, DataBus.VehicleInfo.VehicleSpeed, gradient); + break; + case ResponseUnderload r: //response = Driver.DrivingActionBrake(absTime, ds, DriverStrategy.BrakeTrigger.NextTargetSpeed, // gradient, r); - response = Driver.DrivingActionBrake( - absTime, ds, DataBus.VehicleInfo.VehicleSpeed + r.Driver.Acceleration * r.SimulationInterval, + response = Driver.DrivingActionBrake(absTime, ds, + DataBus.VehicleInfo.VehicleSpeed + r.Driver.Acceleration * r.SimulationInterval, gradient, DataBus.HybridControllerInfo == null ? r : null); if (response != null) { - response.Switch().Case<ResponseGearShift>( - () => { + switch (response) { + case ResponseGearShift _: DataBus.Brakes.BrakePower = 0.SI<Watt>(); - response = Driver.DrivingActionBrake( - absTime, ds, DriverStrategy.BrakeTrigger.NextTargetSpeed, + response = Driver.DrivingActionBrake(absTime, ds, + DriverStrategy.BrakeTrigger.NextTargetSpeed, gradient, DataBus.HybridControllerInfo == null ? r : null); if (response is ResponseOverload) { response = Driver.DrivingActionRoll(absTime, ds, DriverStrategy.BrakeTrigger.NextTargetSpeed, gradient); } - }).Case<ResponseOverload>( - () => { + break; + case ResponseOverload _: DataBus.Brakes.BrakePower = 0.SI<Watt>(); if (DataBus.GearboxInfo.GearboxType.AutomaticTransmission() || DataBus.ClutchInfo.ClutchClosed(absTime)) { if (DataBus.VehicleInfo.VehicleSpeed.IsGreater(0)) { - response = Driver.DrivingActionAccelerate( - absTime, ds, DriverStrategy.BrakeTrigger.NextTargetSpeed, gradient); + response = Driver.DrivingActionAccelerate(absTime, ds, + DriverStrategy.BrakeTrigger.NextTargetSpeed, gradient); } else { if (RetryDistanceExceeded) { response = Driver.DrivingActionAccelerate(absTime, ds, targetVelocity, gradient); @@ -1453,9 +1436,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl } else { response = Driver.DrivingActionRoll(absTime, ds, DriverStrategy.BrakeTrigger.NextTargetSpeed, gradient); } - }); + break; + } } - }); + break; + } //} while (!(response is ResponseSuccess) && i++ < 3); return response; @@ -1528,20 +1513,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl public MeterPerSecond NextTargetSpeed; public Meter TriggerDistance; - public Meter ActionDistance - { - get { - return VectoMath.Min( - CoastingStartDistance ?? double.MaxValue.SI<Meter>(), - BrakingStartDistance ?? double.MaxValue.SI<Meter>()); - } - } + public Meter ActionDistance => VectoMath.Min( + CoastingStartDistance ?? double.MaxValue.SI<Meter>(), + BrakingStartDistance ?? double.MaxValue.SI<Meter>()); - public Meter SelectActionDistance(Meter minDistance) - { - return - new[] { BrakingStartDistance, CoastingStartDistance }.OrderBy(x => x.Value()).First(x => x >= minDistance); - } + public Meter SelectActionDistance(Meter minDistance) => + new[] { BrakingStartDistance, CoastingStartDistance }.OrderBy(x => x.Value()).First(x => x >= minDistance); public Meter CoastingStartDistance { get; set; } diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs index f939777d2f6a43bde3398def11fbeec6671588d4..91b5363bb1cd6b99711a2b5091cda58a51edb0b4 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/DistanceBasedDrivingCycle.cs @@ -317,12 +317,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl CurrentState.Gradient = ComputeGradient(ds); var retVal = NextComponent.Request(absTime, ds, CurrentState.VehicleTargetSpeed, CurrentState.Gradient); - retVal.Switch() - .Case<ResponseFailTimeInterval>( - r => { - retVal = NextComponent.Request(absTime, r.DeltaT, 0.SI<MeterPerSecond>(), CurrentState.Gradient); - retVal = NextComponent.Request(absTime, ds, CurrentState.VehicleTargetSpeed, CurrentState.Gradient); - }); + if (retVal is ResponseFailTimeInterval r) { + // TODO mk20160616 the first assignment to retVal is overwritten. Remove assignment? + retVal = NextComponent.Request(absTime, r.DeltaT, 0.SI<MeterPerSecond>(), CurrentState.Gradient); + retVal = NextComponent.Request(absTime, ds, CurrentState.VehicleTargetSpeed, CurrentState.Gradient); + } CurrentState.AbsTime = absTime; if (retVal is ResponseSuccess) { CurrentState.Distance = PreviousState.Distance + retVal.SimulationDistance; diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Driver.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Driver.cs index 8019d41f1c004b628ed60cc8e01fbd3106bf1a83..7dd3c9926059093453c60ef23102566ce6f32c20 100644 --- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/Driver.cs +++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/Driver.cs @@ -30,6 +30,7 @@ */ using System; +using System.Windows.Forms.DataVisualization.Charting; using TUGraz.VectoCommon.Exceptions; using TUGraz.VectoCommon.Models; using TUGraz.VectoCommon.Utils; @@ -144,9 +145,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl /// <param name="gradient"></param> /// <param name="previousResponse"></param> /// <returns></returns> + /// <returns></returns> public IResponse DrivingActionAccelerate(Second absTime, Meter ds, MeterPerSecond targetVelocity, - Radian gradient, - IResponse previousResponse = null) + Radian gradient, IResponse previousResponse = null) { DrivingAction = DrivingAction.Accelerate; IterationStatistics.Increment(this, "Accelerate"); @@ -155,34 +156,33 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl IResponse retVal = null; DriverAcceleration = operatingPoint.Acceleration; - var response = previousResponse ?? - NextComponent.Request(absTime, operatingPoint.SimulationInterval, operatingPoint.Acceleration, - gradient, false); + var response = previousResponse ?? NextComponent.Request(absTime, operatingPoint.SimulationInterval, operatingPoint.Acceleration, gradient, false); response.Driver.Acceleration = operatingPoint.Acceleration; - response.Switch(). - Case<ResponseSuccess>(r => { + switch (response) { + case ResponseSuccess r: retVal = r; // => return - }). - Case<ResponseOverload>(). // do nothing, searchOperatingPoint is called later on - Case<ResponseEngineSpeedTooHigh>(). // do nothing, searchOperatingPoint is called later on - Case<ResponseUnderload>(r => { + break; + case ResponseOverload _: + break; // do nothing, searchOperatingPoint is called later on + case ResponseEngineSpeedTooHigh _: + break; // do nothing, searchOperatingPoint is called later on + case ResponseUnderload r: // Delta is negative we are already below the Drag-load curve. activate brakes retVal = r; // => return, strategy should brake - }). - Case<ResponseFailTimeInterval>(r => { + break; + case ResponseFailTimeInterval r: // occurs only with AT gearboxes - extend time interval after gearshift! retVal = new ResponseDrivingCycleDistanceExceeded(this) { MaxDistance = r.Driver.Acceleration / 2 * r.DeltaT * r.DeltaT + DataBus.VehicleInfo.VehicleSpeed * r.DeltaT }; - }). - Case<ResponseGearShift>(r => { + break; + case ResponseGearShift r: retVal = r; - }). - Default(r => { - throw new UnexpectedResponseException("DrivingAction Accelerate.", r); - }); - + break; + default: + throw new UnexpectedResponseException("DrivingAction Accelerate.", response); + } if (retVal == null) { // unhandled response (overload, delta > 0) - we need to search for a valid operating point.. @@ -197,11 +197,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl } if (nextOperatingPoint == null && absTime > 0 && DataBus.VehicleInfo.VehicleStopped) { - Log.Info( - "No operating point found! Vehicle stopped! trying HALT action"); + Log.Info("No operating point found! Vehicle stopped! trying HALT action"); DataBus.Brakes.BrakePower = 1.SI<Watt>(); retVal = DrivingActionHalt(absTime, operatingPoint.SimulationInterval, 0.SI<MeterPerSecond>(), gradient); - + retVal.SimulationDistance = 0.SI<Meter>(); retVal.Driver.Acceleration = 0.SI<MeterPerSquareSecond>(); retVal.SimulationInterval = operatingPoint.SimulationInterval; @@ -211,7 +210,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl SimulationInterval = operatingPoint.SimulationInterval }; return retVal; - } + } var limitedOperatingPoint = nextOperatingPoint; if (!(retVal is ResponseEngineSpeedTooHigh || DataBus.ClutchInfo.ClutchClosed(absTime))) { @@ -230,10 +229,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl if (retVal != null) { retVal.Driver.Acceleration = limitedOperatingPoint.Acceleration; } - retVal.Switch(). - Case<ResponseUnderload>(() => operatingPoint = limitedOperatingPoint) - . // acceleration is limited by driver model, operating point moves below drag curve - Case<ResponseOverload>(() => { + + switch (retVal) { + case ResponseUnderload _: + operatingPoint = limitedOperatingPoint; + break; // acceleration is limited by driver model, operating point moves below drag curve + case ResponseOverload _: // deceleration is limited by driver model, operating point moves above full load (e.g., steep uphill) // the vehicle/driver can't achieve an acceleration higher than deceleration curve, try again with higher deceleration if (DataBus.GearboxInfo.GearboxType.AutomaticTransmission()) { @@ -247,13 +248,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl DriverAcceleration = nextOperatingPoint.Acceleration; retVal = NextComponent.Request(absTime, nextOperatingPoint.SimulationInterval, nextOperatingPoint.Acceleration, gradient, false); - retVal.Switch().Case<ResponseFailTimeInterval>( - rt => { - // occurs only with AT gearboxes - extend time interval after gearshift! - retVal = new ResponseDrivingCycleDistanceExceeded(this) { - MaxDistance = DriverAcceleration / 2 * rt.DeltaT * rt.DeltaT + DataBus.VehicleInfo.VehicleSpeed * rt.DeltaT - }; - }); + if (retVal is ResponseFailTimeInterval rt) + // occurs only with AT gearboxes - extend time interval after gearshift! + retVal = new ResponseDrivingCycleDistanceExceeded(this) { MaxDistance = DriverAcceleration / 2 * rt.DeltaT * rt.DeltaT + DataBus.VehicleInfo.VehicleSpeed * rt.DeltaT }; } else { if (absTime > 0 && DataBus.VehicleInfo.VehicleStopped) { Log.Info( @@ -265,76 +262,74 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl //retVal.Acceleration = 0.SI<MeterPerSquareSecond>(); } else { if (response is ResponseEngineSpeedTooHigh) { - Log.Info( - "Operating point with limited acceleration due to high engine speed resulted in an overload, searching again..."); - nextOperatingPoint = SearchOperatingPoint(absTime, ds, gradient, operatingPoint.Acceleration, - retVal); + Log.Info("Operating point with limited acceleration due to high engine speed resulted in an overload, searching again..."); + nextOperatingPoint = SearchOperatingPoint(absTime, ds, gradient, operatingPoint.Acceleration, retVal); DriverAcceleration = nextOperatingPoint.Acceleration; retVal = NextComponent.Request(absTime, nextOperatingPoint.SimulationInterval, nextOperatingPoint.Acceleration, gradient, false); } else { - Log.Info( - "Operating point with limited acceleration resulted in an overload! trying again with original acceleration {0}", + Log.Info("Operating point with limited acceleration resulted in an overload! trying again with original acceleration {0}", nextOperatingPoint.Acceleration); DriverAcceleration = nextOperatingPoint.Acceleration; retVal = NextComponent.Request(absTime, nextOperatingPoint.SimulationInterval, - nextOperatingPoint.Acceleration, - gradient, false); + nextOperatingPoint.Acceleration, gradient, false); } } } retVal.Driver.Acceleration = operatingPoint.Acceleration; - retVal.Switch(). - Case<ResponseDrivingCycleDistanceExceeded>(). - Case<ResponseSuccess>(() => operatingPoint = nextOperatingPoint). - Case<ResponseGearShift>(() => operatingPoint = nextOperatingPoint). - Case<ResponseOverload>( - r => { - nextOperatingPoint = SearchOperatingPoint(absTime, ds, gradient, operatingPoint.Acceleration, - r); - DriverAcceleration = nextOperatingPoint.Acceleration; - retVal = NextComponent.Request(absTime, nextOperatingPoint.SimulationInterval, - nextOperatingPoint.Acceleration, gradient, false); - retVal.Switch().Case<ResponseFailTimeInterval>( - rt => { - // occurs only with AT gearboxes - extend time interval after gearshift! - retVal = new ResponseDrivingCycleDistanceExceeded(this) { - MaxDistance = DriverAcceleration / 2 * rt.DeltaT * rt.DeltaT + DataBus.VehicleInfo.VehicleSpeed * rt.DeltaT - }; - }); - }). - Case<ResponseFailTimeInterval>(r => { + switch (retVal) { + case ResponseDrivingCycleDistanceExceeded _: break; + case ResponseSuccess _: + operatingPoint = nextOperatingPoint; + break; + case ResponseGearShift _: + operatingPoint = nextOperatingPoint; + break; + case ResponseOverload r: + nextOperatingPoint = SearchOperatingPoint(absTime, ds, gradient, operatingPoint.Acceleration, r); + DriverAcceleration = nextOperatingPoint.Acceleration; + retVal = NextComponent.Request(absTime, nextOperatingPoint.SimulationInterval, + nextOperatingPoint.Acceleration, gradient, false); + if (retVal is ResponseFailTimeInterval rt) // occurs only with AT gearboxes - extend time interval after gearshift! retVal = new ResponseDrivingCycleDistanceExceeded(this) { - MaxDistance = r.Driver.Acceleration / 2 * r.DeltaT * r.DeltaT + DataBus.VehicleInfo.VehicleSpeed * r.DeltaT + MaxDistance = DriverAcceleration / 2 * rt.DeltaT * rt.DeltaT + DataBus.VehicleInfo.VehicleSpeed * rt.DeltaT }; - }). - Default( - r => { - throw new UnexpectedResponseException("DrivingAction Accelerate after Overload", r); - }); - }). - Case<ResponseGearShift>(() => operatingPoint = limitedOperatingPoint). - Case<ResponseFailTimeInterval>(r => { + break; + case ResponseFailTimeInterval r: + // occurs only with AT gearboxes - extend time interval after gearshift! + retVal = new ResponseDrivingCycleDistanceExceeded(this) { + MaxDistance = r.Driver.Acceleration / 2 * r.DeltaT * r.DeltaT + DataBus.VehicleInfo.VehicleSpeed * r.DeltaT + }; + break; + default: + throw new UnexpectedResponseException("DrivingAction Accelerate after Overload", retVal); + } + + break; + case ResponseGearShift _: + operatingPoint = limitedOperatingPoint; + break; + case ResponseFailTimeInterval r: // occurs only with AT gearboxes - extend time interval after gearshift! retVal = new ResponseDrivingCycleDistanceExceeded(this) { MaxDistance = r.Driver.Acceleration / 2 * r.DeltaT * r.DeltaT + DataBus.VehicleInfo.VehicleSpeed * r.DeltaT }; - }). - Case<ResponseSuccess>(() => operatingPoint = limitedOperatingPoint). - Case<ResponseBatteryEmpty>(() => { }). - Case<ResponseEngineSpeedTooHigh>(r => { - nextOperatingPoint = SearchOperatingPoint(absTime, ds, gradient, operatingPoint.Acceleration, - r); - retVal = NextComponent.Request(absTime, nextOperatingPoint.SimulationInterval, - nextOperatingPoint.Acceleration, gradient, false); - }). - Default( - r => { - throw new UnexpectedResponseException( - "DrivingAction Accelerate after SearchOperatingPoint.", r); - }); + break; + case ResponseSuccess _: + operatingPoint = limitedOperatingPoint; + break; + case ResponseBatteryEmpty _: + break; + case ResponseEngineSpeedTooHigh r: + nextOperatingPoint = SearchOperatingPoint(absTime, ds, gradient, operatingPoint.Acceleration, r); + retVal = NextComponent.Request(absTime, nextOperatingPoint.SimulationInterval, nextOperatingPoint.Acceleration, gradient, false); + break; + default: + throw new UnexpectedResponseException("DrivingAction Accelerate after SearchOperatingPoint.", retVal); + } } + CurrentState.Acceleration = operatingPoint.Acceleration; CurrentState.dt = operatingPoint.SimulationInterval; CurrentState.Response = retVal; @@ -389,12 +384,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl Log.Debug("DrivingAction Roll"); var retVal = CoastOrRollAction(absTime, ds, maxVelocity, gradient, true); - retVal.Switch(). - Case<ResponseGearShift>( - () => { - throw new UnexpectedResponseException("DrivingAction Roll: Gearshift during Roll action.", - retVal); - }); + if (retVal is ResponseGearShift) + throw new UnexpectedResponseException("DrivingAction Roll: Gearshift during Roll action.", retVal); return retVal; } @@ -502,23 +493,25 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl response.Driver.Acceleration = limitedOperatingPoint.Acceleration; response.Driver.OperatingPoint = limitedOperatingPoint; - response.Switch(). - Case<ResponseSuccess>(). - Case<ResponseUnderload>(). // driver limits acceleration, operating point may be below engine's - //drag load resp. below 0 - Case<ResponseOverload>(). // driver limits acceleration, operating point may be above 0 (GBX), use brakes - Case<ResponseEngineSpeedTooHigh>(). // reduce acceleration/vehicle speed - Case<ResponseGearShift>(). - Case<ResponseFailTimeInterval>(r => { + switch (response) { + case ResponseSuccess _: + break; + case ResponseUnderload _: + break; // driver limits acceleration, operating point may be below engine's drag load resp. below 0 + case ResponseOverload _: + break; // driver limits acceleration, operating point may be above 0 (GBX), use brakes + case ResponseEngineSpeedTooHigh _: + break; // reduce acceleration/vehicle speed + case ResponseGearShift _: + break; + case ResponseFailTimeInterval r: response = new ResponseDrivingCycleDistanceExceeded(this) { MaxDistance = r.Driver.Acceleration / 2 * r.DeltaT * r.DeltaT + DataBus.VehicleInfo.VehicleSpeed * r.DeltaT }; - }). - Default( - () => { - throw new UnexpectedResponseException( - "CoastOrRoll Action: unhandled response from powertrain.", response); - }); + break; + default: + throw new UnexpectedResponseException("CoastOrRoll Action: unhandled response from powertrain.", response); + } CurrentState.Response = response; CurrentState.Acceleration = response.Driver.Acceleration; @@ -534,7 +527,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl if (tc == null) { throw new VectoException("NO TorqueConverter Available!"); } - + if (dryRunResp == null) { throw new VectoException("dry-run response expected!"); } @@ -546,7 +539,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl // out-torque at the torque converter var engineSpeed = DataBus.EngineInfo.EngineIdleSpeed * 1.01; var tcOp = EstimateTCOpPoint(operatingPoint, dryRunResp, engineSpeed, tcInfo); - + if (tcOp.Item1.Item2.IsBetween(tcOp.Item2, tcOp.Item3)) { if (!dryRunResp.TorqueConverter.TorqueConverterOperatingPoint.OutTorque.IsEqual(tcOp.Item1.Item1.OutTorque)) { tc.SetOperatingPoint = tcOp.Item1.Item1; @@ -595,7 +588,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl }); } catch (Exception e) { Log.Error(e, "Failed to find engine speed for valid torque converter operating point! absTime: {0}", absTime); - + // if no engine speed can be found that results in an operating point on the TC curve, set the TC in-torque to the maximum // available from the engine. reverse-calc TC-in-torque from average engine torque var tcInPwrPrev = (DataBus.EngineInfo.EngineSpeed + tcOp.Item1.Item1.InAngularVelocity) * tcOp.Item1.Item2 - @@ -682,17 +675,17 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { var deltaSpeed = VectoMath.Min(0.RPMtoRad(), tqOp.Item1.InAngularVelocity - DataBus.EngineInfo.EngineIdleSpeed) + VectoMath.Max(0.RPMtoRad(), tqOp.Item1.InAngularVelocity - DataBus.EngineInfo.EngineRatedSpeed); - var tqDiff = 0.SI<NewtonMeter>(); + var tqDiff = 0.SI<NewtonMeter>(); if (tqOp.Item2.IsSmaller(dragTorque)) { tqDiff = tqOp.Item2 - dragTorque; - + } if (tqOp.Item2.IsGreater(maxTorque)) { - tqDiff = tqOp.Item2 - maxTorque; + tqDiff = tqOp.Item2 - maxTorque; } return ((tqDiff.Value() * tqDiff.Value()) + (deltaSpeed.Value() * deltaSpeed.Value())).SI<NewtonMeter>(); - + } public IResponse DrivingActionBrake(Second absTime, Meter ds, MeterPerSecond nextTargetSpeed, Radian gradient, IResponse previousResponse = null, Meter targetDistance = null, DrivingAction? overrideAction = null) @@ -720,24 +713,29 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl gradient, false); var point = operatingPoint; - response.Switch(). - Case<ResponseSuccess>(r => retVal = r). - Case<ResponseOverload>(r => retVal = r) - . // i.e., driving uphill, clutch open, deceleration higher than desired deceleration - Case<ResponseUnderload>(). // will be handled in SearchBrakingPower - Case<ResponseEngineSpeedTooHigh>(r => { + switch (response) { + case ResponseSuccess r: + retVal = r; + break; + case ResponseOverload r: + retVal = r; + break; // i.e., driving uphill, clutch open, deceleration higher than desired deceleration + case ResponseUnderload _: + break; // will be handled in SearchBrakingPower + case ResponseEngineSpeedTooHigh r: Log.Debug("Engine speeed was too high, search for appropriate acceleration first."); - operatingPoint = SearchOperatingPoint(absTime, ds, gradient, point.Acceleration, - response); - }). // will be handled in SearchBrakingPower - Case<ResponseGearShift>(). // will be handled in SearchBrakingPower - Case<ResponseFailTimeInterval>(r => + operatingPoint = SearchOperatingPoint(absTime, ds, gradient, point.Acceleration, response); + break; // will be handled in SearchBrakingPower + case ResponseGearShift _: + break; // will be handled in SearchBrakingPower + case ResponseFailTimeInterval r: retVal = new ResponseDrivingCycleDistanceExceeded(this) { MaxDistance = DataBus.VehicleInfo.VehicleSpeed * r.DeltaT + point.Acceleration / 2 * r.DeltaT * r.DeltaT - }). - Default(r => { - throw new UnexpectedResponseException("DrivingAction Brake: first request.", r); - }); + }; + break; + default: + throw new UnexpectedResponseException("DrivingAction Brake: first request.", response); + } if (retVal != null) { CurrentState.Acceleration = operatingPoint.Acceleration; @@ -789,7 +787,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl gradient, false); var gearChanged = !(DataBus.GearboxInfo.Gear == gear && DataBus.GearboxInfo.TCLocked == tcLocked); if (DataBus.GearboxInfo.GearboxType.AutomaticTransmission() && gearChanged && (retVal is ResponseOverload || retVal is ResponseUnderload)) { - Log.Debug("Gear changed after a valid operating point was found - braking is no longer applicable due to overload"); + Log.Debug("Gear changed after a valid operating point was found - braking is no longer applicable due to overload"); return null; } @@ -811,15 +809,15 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl gradient, false); } - retVal.Switch(). - Case<ResponseSuccess>(). - Case<ResponseGearShift>(). - Case<ResponseFailTimeInterval>(r => + switch (retVal) { + case ResponseSuccess _: break; + case ResponseGearShift _: break; + case ResponseFailTimeInterval r: retVal = new ResponseDrivingCycleDistanceExceeded(this) { - MaxDistance = - DataBus.VehicleInfo.VehicleSpeed * r.DeltaT + operatingPoint.Acceleration / 2 * r.DeltaT * r.DeltaT - }). - Case<ResponseUnderload>(r => { + MaxDistance = DataBus.VehicleInfo.VehicleSpeed * r.DeltaT + operatingPoint.Acceleration / 2 * r.DeltaT * r.DeltaT + }; + break; + case ResponseUnderload r: if (DataBus.GearboxInfo.GearboxType.AutomaticTransmission()) { operatingPoint = SearchBrakingPower(absTime, operatingPoint.SimulationDistance, gradient, operatingPoint.Acceleration, response); @@ -827,21 +825,21 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl retVal = NextComponent.Request(absTime, operatingPoint.SimulationInterval, operatingPoint.Acceleration, gradient, false); } - }). - Case<ResponseOverload>(r => { + break; + case ResponseOverload r: if (DataBus.GearboxInfo.GearboxType.AutomaticTransmission()) { // overload may happen because of gearshift between search and actual request, search again var i = 5; while (i-- > 0 && !(retVal is ResponseSuccess)) { DataBus.Brakes.BrakePower = 0.SI<Watt>(); - + retVal = NextComponent.Request( absTime, operatingPoint.SimulationInterval, operatingPoint.Acceleration, gradient, false); if (retVal is ResponseSuccess) { break; } - + operatingPoint = SearchBrakingPower(absTime, operatingPoint.SimulationDistance, gradient, operatingPoint.Acceleration, retVal); DriverAcceleration = operatingPoint.Acceleration; @@ -857,13 +855,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl throw new UnexpectedResponseException( "DrivingAction Brake: request failed after braking power was found.", r); } - }). - Default( - r => { - throw new UnexpectedResponseException( - "DrivingAction Brake: request failed after braking power was found.", r); - }); - + + break; + default: + throw new UnexpectedResponseException("DrivingAction Brake: request failed after braking power was found.", retVal); + } + CurrentState.Acceleration = operatingPoint.Acceleration; CurrentState.dt = operatingPoint.SimulationInterval; CurrentState.Response = retVal; @@ -1006,29 +1003,27 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl var operatingPoint = new OperatingPoint { SimulationDistance = ds, Acceleration = acceleration }; operatingPoint = ComputeTimeInterval(operatingPoint.Acceleration, ds); Watt deltaPower = null; - initialResponse.Switch(). - Case<ResponseGearShift>(r => { + switch (initialResponse) { + case ResponseGearShift r: IterationStatistics.Increment(this, "SearchBrakingPower"); DriverAcceleration = operatingPoint.Acceleration; var nextResp = NextComponent.Request(absTime, operatingPoint.SimulationInterval, - operatingPoint.Acceleration, - gradient, true); + operatingPoint.Acceleration, gradient, true); deltaPower = nextResp.Gearbox.PowerRequest; - }). - Case<ResponseEngineSpeedTooHigh>(r => { + break; + case ResponseEngineSpeedTooHigh r: IterationStatistics.Increment(this, "SearchBrakingPower"); DriverAcceleration = operatingPoint.Acceleration; - var nextResp = NextComponent.Request(absTime, operatingPoint.SimulationInterval, - operatingPoint.Acceleration, - gradient, true); - deltaPower = nextResp.Gearbox.PowerRequest; - }). - Case<ResponseUnderload>(r => - deltaPower = DataBus.ClutchInfo.ClutchClosed(absTime) && DataBus.GearboxInfo.GearEngaged(absTime) ? r.Delta : r.Gearbox.PowerRequest). - Default( - r => { - throw new UnexpectedResponseException("cannot use response for searching braking power!", r); - }); + var nextResp1 = NextComponent.Request(absTime, operatingPoint.SimulationInterval, + operatingPoint.Acceleration, gradient, true); + deltaPower = nextResp1.Gearbox.PowerRequest; + break; + case ResponseUnderload r: + deltaPower = DataBus.ClutchInfo.ClutchClosed(absTime) && DataBus.GearboxInfo.GearEngaged(absTime) ? r.Delta : r.Gearbox.PowerRequest; + break; + default: + throw new UnexpectedResponseException("cannot use response for searching braking power!", initialResponse); + } try { DataBus.Brakes.BrakePower = SearchAlgorithm.Search(DataBus.Brakes.BrakePower, deltaPower, @@ -1125,7 +1120,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl var response = NextComponent.Request(absTime, retVal.SimulationInterval, acc, gradient, true); response.Driver.OperatingPoint = retVal; return response; - + }, criterion: response => { var r = (ResponseDryRun)response; @@ -1166,7 +1161,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl // calculate new time interval only when vehiclespeed and acceleration are != 0 // else: use same timeinterval as before. var vehicleDrivesAndAccelerates = - !(acc.IsEqual(0) && DataBus.VehicleInfo.VehicleSpeed.IsEqual(0)); + !(acc.IsEqual(0) && DataBus.VehicleInfo.VehicleSpeed.IsEqual(0)); if (vehicleDrivesAndAccelerates) { var tmp = ComputeTimeInterval(acc, ds); if (tmp.SimulationInterval.IsEqual(0.SI<Second>(), 1e-9.SI<Second>())) { @@ -1232,23 +1227,34 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl { Watt origDelta = null; if (actionRoll) { - initialResponse.Switch(). - Case<ResponseDryRun>(r => origDelta = r.Gearbox.PowerRequest). - Case<ResponseOverload>(r => origDelta = r.Delta). - Case<ResponseFailTimeInterval>(r => origDelta = r.Gearbox.PowerRequest). - Default(r => { - throw new UnexpectedResponseException("SearchOperatingPoint: Unknown response type.", r); - }); + switch (initialResponse) { + case ResponseDryRun r: + origDelta = r.Gearbox.PowerRequest; + break; + case ResponseOverload r: + origDelta = r.Delta; + break; + case ResponseFailTimeInterval r: + origDelta = r.Gearbox.PowerRequest; + break; + default: + throw new UnexpectedResponseException("SearchOperatingPoint: Unknown response type.", initialResponse); + } } else { - initialResponse.Switch(). - Case<ResponseOverload>(r => origDelta = r.Delta). - Case<ResponseEngineSpeedTooHigh>(r => { + switch (initialResponse) { + case ResponseOverload r: + origDelta = r.Delta; + break; + case ResponseEngineSpeedTooHigh r: + // search operating point in drive action after overload origDelta = r.DeltaEngineSpeed * 1.SI<NewtonMeter>(); - }). // search operating point in drive action after overload - Case<ResponseDryRun>(r => origDelta = coastingOrRoll ? r.DeltaDragLoad : r.DeltaFullLoad). - Default(r => { - throw new UnexpectedResponseException("SearchOperatingPoint: Unknown response type.", r); - }); + break; + case ResponseDryRun r: + origDelta = coastingOrRoll ? r.DeltaDragLoad : r.DeltaFullLoad; + break; + default: + throw new UnexpectedResponseException("SearchOperatingPoint: Unknown response type.", initialResponse); + } } return origDelta; } @@ -1353,11 +1359,10 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl DriverAcceleration = 0.SI<MeterPerSquareSecond>(); var retVal = NextComponent.Request(absTime, dt, 0.SI<MeterPerSquareSecond>(), gradient, false); - retVal.Switch(). - Case<ResponseGearShift>(r => { - DriverAcceleration = 0.SI<MeterPerSquareSecond>(); - retVal = NextComponent.Request(absTime, dt, 0.SI<MeterPerSquareSecond>(), gradient, false); - }); + if (retVal is ResponseGearShift) { + DriverAcceleration = 0.SI<MeterPerSquareSecond>(); + retVal = NextComponent.Request(absTime, dt, 0.SI<MeterPerSquareSecond>(), gradient, false); + } CurrentState.dt = dt; CurrentState.Acceleration = 0.SI<MeterPerSquareSecond>(); return retVal; @@ -1371,7 +1376,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl DriverStrategy.WriteModalResults(container); } - + protected override void DoCommitSimulationStep(Second time, Second simulationInterval) { if (CurrentState.Response != null && !(CurrentState.Response is ResponseSuccess)) {