Code development platform for open source projects from the European Union institutions

Skip to content
Snippets Groups Projects
Commit e211a88b authored by Michael KRISPER's avatar Michael KRISPER
Browse files

replace many switch-functions by switch-patterns

parent 9e519f0d
No related branches found
No related tags found
No related merge requests found
......@@ -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 = {
......
......@@ -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;
}
}
......
......@@ -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; }
......
......@@ -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;
......
......@@ -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)) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment