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

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

ShiftStrategy: Introduced BaseShiftStrategy

parent ce3659ee
No related branches found
No related tags found
No related merge requests found
......@@ -90,14 +90,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent
/// </value>
IGearbox Gearbox { get; set; }
GearInfo NextGear { get; }
GearInfo NextGear { get; }
}
public class GearInfo
{
public uint Gear;
public bool TorqueConverterLocked;
}
public class GearInfo
{
public uint Gear;
public bool TorqueConverterLocked;
}
}
\ No newline at end of file
......@@ -52,26 +52,26 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
private bool SpeedTooLowForEngine(uint gear, PerSecond outAngularSpeed)
{
return (outAngularSpeed * Data.Gears[gear].Ratio).IsSmaller(DataBus.EngineIdleSpeed);
return (outAngularSpeed * ModelData.Gears[gear].Ratio).IsSmaller(DataBus.EngineIdleSpeed);
}
private bool SpeedTooHighForEngine(uint gear, PerSecond outAngularSpeed)
{
return
(outAngularSpeed * Data.Gears[gear].Ratio).IsGreaterOrEqual(DataBus.EngineN95hSpeed);
(outAngularSpeed * ModelData.Gears[gear].Ratio).IsGreaterOrEqual(DataBus.EngineN95hSpeed);
}
public override GearInfo NextGear
{
get { return new GearInfo(){Gear = _nextGear, TorqueConverterLocked = false}; }
}
public override GearInfo NextGear
{
get { return new GearInfo() { Gear = _nextGear, TorqueConverterLocked = false }; }
}
public override uint Engage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity)
public override uint Engage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity)
{
while (_nextGear > 1 && SpeedTooLowForEngine(_nextGear, outAngularVelocity)) {
_nextGear--;
}
while (_nextGear < Data.Gears.Count && SpeedTooHighForEngine(_nextGear, outAngularVelocity)) {
while (_nextGear < ModelData.Gears.Count && SpeedTooHighForEngine(_nextGear, outAngularVelocity)) {
_nextGear++;
}
......@@ -83,8 +83,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
public override uint InitGear(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity)
{
if (DataBus.VehicleSpeed.IsEqual(0)) {
for (var gear = (uint)Data.Gears.Count; gear > 1; gear--) {
var inAngularSpeed = outAngularVelocity * Data.Gears[gear].Ratio;
for (var gear = (uint)ModelData.Gears.Count; gear > 1; gear--) {
var inAngularSpeed = outAngularVelocity * ModelData.Gears[gear].Ratio;
var ratedSpeed = DataBus.EngineRatedSpeed;
if (inAngularSpeed > ratedSpeed || inAngularSpeed.IsEqual(0)) {
......@@ -99,23 +99,23 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
// if in shift curve and above idle speed and torque reserve is provided.
if (!IsBelowDownShiftCurve(gear, inTorque, inAngularSpeed) && inAngularSpeed > DataBus.EngineIdleSpeed &&
reserve >= Data.StartTorqueReserve) {
reserve >= ModelData.StartTorqueReserve) {
return gear;
}
}
return 1;
}
for (var gear = (uint)Data.Gears.Count; gear > 1; gear--) {
for (var gear = (uint)ModelData.Gears.Count; gear > 1; gear--) {
var response = _gearbox.Initialize(gear, outTorque, outAngularVelocity);
var inAngularSpeed = outAngularVelocity * Data.Gears[gear].Ratio;
var inAngularSpeed = outAngularVelocity * ModelData.Gears[gear].Ratio;
var fullLoadPower = response.EnginePowerRequest - response.DeltaFullLoad;
var reserve = 1 - response.EnginePowerRequest / fullLoadPower;
var inTorque = response.ClutchPowerRequest / inAngularSpeed;
// if in shift curve and torque reserve is provided: return the current gear
if (!IsBelowDownShiftCurve(gear, inTorque, inAngularSpeed) && !IsAboveUpShiftCurve(gear, inTorque, inAngularSpeed) &&
reserve >= Data.StartTorqueReserve) {
reserve >= ModelData.StartTorqueReserve) {
if ((inAngularSpeed - DataBus.EngineIdleSpeed) / (DataBus.EngineRatedSpeed - DataBus.EngineIdleSpeed) <
Constants.SimulationSettings.ClutchClosingSpeedNorm && gear > 1) {
gear--;
......@@ -125,7 +125,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
}
// if over the up shift curve: return the previous gear (even thou it did not provide the required torque reserve)
if (IsAboveUpShiftCurve(gear, inTorque, inAngularSpeed) && gear < Data.Gears.Count) {
if (IsAboveUpShiftCurve(gear, inTorque, inAngularSpeed) && gear < ModelData.Gears.Count) {
return gear + 1;
}
}
......@@ -147,7 +147,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
while (_nextGear > 1 && SpeedTooLowForEngine(_nextGear, outAngularVelocity)) {
_nextGear--;
}
while (_nextGear < Data.Gears.Count && SpeedTooHighForEngine(_nextGear, outAngularVelocity)) {
while (_nextGear < ModelData.Gears.Count && SpeedTooHighForEngine(_nextGear, outAngularVelocity)) {
_nextGear++;
}
if (_nextGear != gear) {
......@@ -155,7 +155,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
}
// normal shift when all requirements are fullfilled ------------------
var minimumShiftTimePassed = (lastShiftTime + Data.ShiftTime).IsSmallerOrEqual(absTime);
var minimumShiftTimePassed = (lastShiftTime + ModelData.ShiftTime).IsSmallerOrEqual(absTime);
if (!minimumShiftTimePassed) {
return false;
}
......@@ -167,7 +167,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
_nextGear = CheckUpshift(absTime, dt, outTorque, outAngularVelocity, inTorque, inAngularVelocity, gear);
if ((Data.Gears[_nextGear].Ratio * outAngularVelocity - DataBus.EngineIdleSpeed) /
if ((ModelData.Gears[_nextGear].Ratio * outAngularVelocity - DataBus.EngineIdleSpeed) /
(DataBus.EngineRatedSpeed - DataBus.EngineIdleSpeed) <
Constants.SimulationSettings.ClutchClosingSpeedNorm && _nextGear > 1) {
_nextGear--;
......@@ -233,12 +233,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
var response = (ResponseDryRun)_gearbox.Request(absTime, dt, outTorque, outAngularVelocity, true);
_gearbox.Gear = tmpGear;
inAngularVelocity = Data.Gears[currentGear].Ratio * outAngularVelocity;
inAngularVelocity = ModelData.Gears[currentGear].Ratio * outAngularVelocity;
inTorque = response.ClutchPowerRequest / inAngularVelocity;
}
// early up shift to higher gear ---------------------------------------
if (EarlyShiftUp && currentGear < Data.Gears.Count) {
if (EarlyShiftUp && currentGear < ModelData.Gears.Count) {
// try if next gear would provide enough torque reserve
var tryNextGear = currentGear + 1;
var tmpGear = Gearbox.Gear;
......@@ -246,7 +246,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
var response = (ResponseDryRun)_gearbox.Request(absTime, dt, outTorque, outAngularVelocity, true);
_gearbox.Gear = tmpGear;
inAngularVelocity = Data.Gears[tryNextGear].Ratio * outAngularVelocity;
inAngularVelocity = ModelData.Gears[tryNextGear].Ratio * outAngularVelocity;
inTorque = response.ClutchPowerRequest / inAngularVelocity;
// if next gear supplied enough power reserve: take it
......@@ -255,7 +255,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
var fullLoadPower = response.EnginePowerRequest - response.DeltaFullLoad;
var reserve = 1 - response.EnginePowerRequest / fullLoadPower;
if (reserve >= Data.TorqueReserve) {
if (reserve >= ModelData.TorqueReserve) {
currentGear = tryNextGear;
}
}
......@@ -277,7 +277,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
var response = (ResponseDryRun)_gearbox.Request(absTime, dt, outTorque, outAngularVelocity, true);
_gearbox.Gear = tmpGear;
inAngularVelocity = Data.Gears[currentGear].Ratio * outAngularVelocity;
inAngularVelocity = ModelData.Gears[currentGear].Ratio * outAngularVelocity;
inTorque = response.ClutchPowerRequest / inAngularVelocity;
}
return currentGear;
......
......@@ -32,7 +32,6 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using TUGraz.VectoCommon.Exceptions;
using TUGraz.VectoCommon.Models;
using TUGraz.VectoCommon.Utils;
using TUGraz.VectoCore.Configuration;
using TUGraz.VectoCore.Models.Simulation.DataBus;
......@@ -40,37 +39,46 @@ using TUGraz.VectoCore.Models.SimulationComponent.Data;
namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
{
public class ATShiftStrategy : LoggingObject, IShiftStrategy
public class ATShiftStrategy : BaseShiftStrategy
{
private readonly GearboxData _data;
private readonly IDataBus _dataBus;
private ATGearbox _gearbox;
private readonly NextGearState _nextGear;
private readonly NextGearState _nextGear = new NextGearState();
public ATShiftStrategy(GearboxData data, IDataBus dataBus)
public override IGearbox Gearbox
{
_data = data;
_dataBus = dataBus;
_nextGear = new NextGearState();
get { return _gearbox; }
set
{
_gearbox = value as ATGearbox;
if (_gearbox == null) {
throw new VectoException("AT Shift strategy can only handle AT gearboxes, given: {0}", value.GetType());
}
}
}
//public ATGearbox Gearbox { get; protected internal set; }
public override GearInfo NextGear
{
get { return new GearInfo { Gear = _nextGear.Gear, TorqueConverterLocked = _nextGear.TorqueConverterLocked }; }
}
public ATShiftStrategy(GearboxData data, IDataBus dataBus) : base(data, dataBus) {}
public uint InitGear(Second absTime, Second dt, NewtonMeter torque, PerSecond outAngularVelocity)
public override uint InitGear(Second absTime, Second dt, NewtonMeter torque, PerSecond outAngularVelocity)
{
if (_dataBus.VehicleSpeed.IsEqual(0)) {
if (DataBus.VehicleSpeed.IsEqual(0)) {
// AT always starts in first gear and TC active!
_gearbox.TorqueConverterLocked = false;
_gearbox.Disengaged = true;
return 1; // AT always starts in first gear!
return 1;
}
var torqueConverterLocked = true;
for (var gear = _data.Gears.Keys.Max(); gear > 1; gear--) {
for (var gear = ModelData.Gears.Keys.Max(); gear > 1; gear--) {
if (_gearbox.ModelData.Gears[gear].HasTorqueConverter) {
torqueConverterLocked = false;
}
var response = _gearbox.Initialize(gear, torqueConverterLocked, torque, outAngularVelocity);
if (response.EngineSpeed > _dataBus.EngineRatedSpeed || response.EngineSpeed < _dataBus.EngineIdleSpeed) {
if (response.EngineSpeed > DataBus.EngineRatedSpeed || response.EngineSpeed < DataBus.EngineIdleSpeed) {
continue;
}
......@@ -86,63 +94,84 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
return 1;
}
public bool ShiftRequired(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity,
public override uint Engage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity)
{
if (_nextGear.AbsTime != null && _nextGear.AbsTime.IsEqual(absTime)) {
_gearbox.TorqueConverterLocked = _nextGear.TorqueConverterLocked;
_gearbox.Disengaged = _nextGear.Disengaged;
_nextGear.AbsTime = null;
return _nextGear.Gear;
}
_nextGear.AbsTime = null;
return _gearbox.Gear;
}
public override void Disengage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outEngineSpeed)
{
throw new System.NotImplementedException("AT Shift Strategy does not support disengaging.");
}
public override bool ShiftRequired(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity,
NewtonMeter inTorque, PerSecond inAngularVelocity, uint gear, Second lastShiftTime)
{
// 0 -> 1C: drive off after stop - engage first gear
// ENGAGE ---------------------------------------------------------
// 0 -> 1C: drive off after disengaged - engage first gear
if (_gearbox.Disengaged && outAngularVelocity.IsGreater(0.SI<PerSecond>())) {
Log.Debug("shift requried: drive off after vehicle stopped");
_nextGear.SetState(absTime, false, 1, false);
Log.Debug("shift required: drive off after vehicle stopped");
_nextGear.SetState(absTime, disengaged: false, gear: 1, tcLocked: false);
return true;
}
// _ -> 0: disengage before halting
if (_dataBus.DriverBehavior == DrivingBehavior.Braking && outTorque.IsSmaller(0) &&
_dataBus.VehicleSpeed.IsSmaller(Constants.SimulationSettings.ATGearboxDisengageWhenHaltingSpeed)) {
_nextGear.SetState(absTime, true, 1, false);
return true;
}
// DISENGAGE ------------------------------------------------------
// 1) _ -> 0: disengage before halting
var braking = DataBus.DriverBehavior == DrivingBehavior.Braking;
var torqueNegative = outTorque.IsSmaller(0);
var slowerThanDisengageSpeed =
DataBus.VehicleSpeed.IsSmaller(Constants.SimulationSettings.ATGearboxDisengageWhenHaltingSpeed);
var disengageBeforeHalting = braking && torqueNegative && slowerThanDisengageSpeed;
// 1C -> 0: disengange when negative T_out and positive T_in
if (gear == 1 && !_gearbox.TorqueConverterLocked && outTorque.IsSmaller(0) && inTorque.IsGreater(0)) {
_nextGear.SetState(absTime, true, 1, false);
return true;
}
// 2) L -> 0: disengage if inAngularVelocity == 0
var disengageAngularVelocityZero = _gearbox.TorqueConverterLocked && inAngularVelocity.IsEqual(0.SI<PerSecond>());
if (inAngularVelocity == null) {
return false;
}
// 3) 1C -> 0: disengange when negative T_out and positive T_in
var gear1C = gear == 1 && !_gearbox.TorqueConverterLocked;
var disengageTOutNegativeAndTInPositive = gear1C && outTorque.IsSmaller(0) && inTorque.IsGreater(0);
var disengageTCEngineSpeedLowerIdle = braking && torqueNegative && gear1C &&
inAngularVelocity.IsSmallerOrEqual(DataBus.EngineIdleSpeed);
// L -> 0: disengage if inAngularVelocity == 0
if (_gearbox.TorqueConverterLocked && inAngularVelocity.IsEqual(0.SI<PerSecond>())) {
_nextGear.SetState(absTime, true, 1, false);
if (disengageBeforeHalting || disengageTCEngineSpeedLowerIdle || disengageAngularVelocityZero ||
disengageTOutNegativeAndTInPositive) {
_nextGear.SetState(absTime, disengaged: true, gear: 1, tcLocked: false);
return true;
}
// EMERGENCY SHIFTS ---------------------------------------
// Emergency Downshift: if lower than engine idle speed
if (inAngularVelocity.IsSmaller(_dataBus.EngineIdleSpeed)) {
if (inAngularVelocity.IsSmaller(DataBus.EngineIdleSpeed)) {
Log.Debug("engine speed would fall below idle speed - shift down");
Downshift(absTime, gear);
return true;
}
// Emergency Upshift: if higher than engine rated speed
if (inAngularVelocity.IsGreaterOrEqual(_dataBus.EngineRatedSpeed) && _data.Gears.ContainsKey(gear + 1)) {
if (inAngularVelocity.IsGreaterOrEqual(DataBus.EngineRatedSpeed)) {
// upshift is not possible
if (ModelData.Gears.ContainsKey(gear + 1)) {
return false;
}
Log.Debug("engine speed would be above rated speed - shift up");
Upshift(absTime, gear);
return true;
}
if ((absTime - lastShiftTime).IsSmaller(_data.ShiftTime)) {
return false;
}
if (CheckDownshift(absTime, dt, outTorque, outAngularVelocity, inTorque, inAngularVelocity, gear,
// UPSHIFT --------------------------------------------------------
if (CheckUpshift(absTime, dt, outTorque, outAngularVelocity, inTorque, inAngularVelocity, gear,
lastShiftTime)) {
return true;
}
if (CheckUpshift(absTime, dt, outTorque, outAngularVelocity, inTorque, inAngularVelocity, gear,
// DOWNSHIFT ------------------------------------------------------
if (CheckDownshift(absTime, dt, outTorque, outAngularVelocity, inTorque, inAngularVelocity, gear,
lastShiftTime)) {
return true;
}
......@@ -150,85 +179,74 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
return false;
}
private void Upshift(Second absTime, uint gear)
{
// C -> L: switch from torque converter to locked gear
if (!_gearbox.TorqueConverterLocked && _data.Gears[gear].HasLockedGear) {
_nextGear.SetState(absTime, false, gear, true);
return;
}
// L -> L+1
// C -> C+1
if (_data.Gears.ContainsKey(gear + 1)) {
_nextGear.SetState(absTime, false, gear + 1, _gearbox.TorqueConverterLocked);
return;
}
// C -> L+1 -- not allowed!!
throw new VectoSimulationException(
"ShiftStrategy wanted to shift up, but current gear has active torque converter (C) but no locked gear (no L) and shifting directly to (L) is not allowed.");
}
private void Downshift(Second absTime, uint gear)
{
// L -> C
if (_gearbox.TorqueConverterLocked && _data.Gears[gear].HasTorqueConverter) {
_nextGear.SetState(absTime, false, gear, false);
return;
}
// L -> L-1
// C -> C-1
if (_data.Gears.ContainsKey(gear - 1)) {
_nextGear.SetState(absTime, false, gear - 1, _gearbox.TorqueConverterLocked);
return;
}
// L -> 0 -- not allowed!!
throw new VectoSimulationException(
"ShiftStrategy wanted to shift down but current gear is locked (L) and has no torque converter (C) and disenganging directly from (L) is not allowed.");
}
[SuppressMessage("ReSharper", "UnusedParameter.Local")]
private bool CheckUpshift(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity,
NewtonMeter inTorque, PerSecond inAngularVelocity, uint gear, Second lastShiftTime)
{
if (_gearbox.TorqueConverterLocked || _data.Gears[gear].HasLockedGear) {
// L -> L+1
var shiftTimeReached = (absTime - lastShiftTime).IsGreaterOrEqual(ModelData.ShiftTime);
if (!shiftTimeReached)
return false;
var currentGear = ModelData.Gears[gear];
if (_gearbox.TorqueConverterLocked || currentGear.HasLockedGear) {
// UPSHIFT - General Rule
// L -> L+1
// C -> L
var nextGear = _gearbox.TorqueConverterLocked ? gear + 1 : gear;
if (!_data.Gears.ContainsKey(nextGear)) {
if (!ModelData.Gears.ContainsKey(nextGear)) {
return false;
}
var nextEngineSpeed = outAngularVelocity * _data.Gears[nextGear].Ratio;
var enginePower = inAngularVelocity * inTorque;
var nextEngineSpeed = outAngularVelocity * ModelData.Gears[nextGear].Ratio;
if (nextEngineSpeed.IsEqual(0)) {
return false;
}
if (
IsAboveUpShiftCurve(gear, enginePower / nextEngineSpeed, nextEngineSpeed,
_gearbox.TorqueConverterLocked) &&
enginePower.IsSmallerOrEqual(_dataBus.EngineStationaryFullPower(nextEngineSpeed))) {
var currentEnginePower = inTorque * inAngularVelocity;
var nextEnginePower = currentEnginePower / nextEngineSpeed;
var isAboveUpShift = IsAboveUpShiftCurve(gear, nextEnginePower, nextEngineSpeed, _gearbox.TorqueConverterLocked);
//var engineCanSupplyPower =
// currentEnginePower.IsSmallerOrEqual(DataBus.EngineStationaryFullPower(nextEngineSpeed));
var reachableAcceleration = EstimateAccelerationForGear(nextGear, outAngularVelocity);
var minAcceleration = _gearbox.TorqueConverterLocked
? ModelData.UpshiftMinAcceleration
: ModelData.TorqueConverterData.UpshiftMinAcceleration;
var minAccelerationReachable = reachableAcceleration.IsGreaterOrEqual(minAcceleration);
// todo mk-2016-12-19: check that accMin can be reached!
// todo l->l+1 LaccMin must be reachable
// todo C->l TCLaccMin must be reachable
// todo acc > min(driver-demand-acc, accMin)
if (isAboveUpShift && minAccelerationReachable) {
Upshift(absTime, gear);
return true;
}
}
if (!_gearbox.TorqueConverterLocked && _data.Gears.ContainsKey(gear + 1) &&
_data.Gears[gear + 1].HasTorqueConverter) {
// UPSHIFT - Special rule for 1C -> 2C
if (!_gearbox.TorqueConverterLocked && ModelData.Gears.ContainsKey(gear + 1) &&
ModelData.Gears[gear + 1].HasTorqueConverter) {
// C -> C+1
var gearRatio = _data.Gears[gear + 1].TorqueConverterRatio / _data.Gears[gear].TorqueConverterRatio;
var minEngineSpeed = VectoMath.Min(700.RPMtoRad(),
gearRatio * (_dataBus.EngineN80hSpeed - 150.RPMtoRad()));
var nextGbxInSpeed = outAngularVelocity * _data.Gears[gear + 1].TorqueConverterRatio;
var nextGbxInTorque = outTorque / _data.Gears[gear + 1].TorqueConverterRatio;
var tcOperatingPoint = _gearbox.TorqueConverter.FindOperatingPoint(nextGbxInTorque, nextGbxInSpeed);
if (tcOperatingPoint.InAngularVelocity.IsGreater(minEngineSpeed) &&
_dataBus.EngineStationaryFullPower(tcOperatingPoint.InAngularVelocity)
.IsGreater(0.7 * _dataBus.EngineStationaryFullPower(inAngularVelocity))) {
var nextGear = ModelData.Gears[gear + 1];
var gearRatio = nextGear.TorqueConverterRatio / currentGear.TorqueConverterRatio;
var minEngineSpeed = VectoMath.Min(700.RPMtoRad(), gearRatio * (DataBus.EngineN80hSpeed - 150.RPMtoRad()));
var nextGearboxInSpeed = outAngularVelocity * nextGear.TorqueConverterRatio;
var nextGearboxInTorque = outTorque / nextGear.TorqueConverterRatio;
var tcOperatingPoint = _gearbox.TorqueConverter.FindOperatingPoint(nextGearboxInTorque, nextGearboxInSpeed);
var engineSpeedOverMin = tcOperatingPoint.InAngularVelocity.IsGreater(minEngineSpeed);
// todo mk-2016-12-19: calculate accelerationReachable with param TCCaccMin: acc > min(driver-demand-acc, TCCaccMin)
//var engineCanSupplyPower = DataBus.EngineStationaryFullPower(tcOperatingPoint.InAngularVelocity)
// .IsGreater(0.7 * DataBus.EngineStationaryFullPower(inAngularVelocity));
var minAccelerationReachable = true;
if (shiftTimeReached && engineSpeedOverMin && minAccelerationReachable) {
Upshift(absTime, gear);
return true;
}
......@@ -236,61 +254,62 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
return false;
}
[SuppressMessage("ReSharper", "UnusedParameter.Local")]
private bool CheckDownshift(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity,
NewtonMeter inTorque, PerSecond inAngularVelocity, uint gear, Second lastShiftTime)
/// <summary>
/// Tests if the operating point is above (right of) the up-shift curve.
/// </summary>
/// <param name="gear">The gear.</param>
/// <param name="inTorque">The in torque.</param>
/// <param name="inEngineSpeed">The in engine speed.</param>
/// <param name="torqueConverterLocked">if true, the regular shift polygon is used, otherwise the shift polygon for the torque converter is used</param>
/// <returns><c>true</c> if the operating point is above the up-shift curve; otherwise, <c>false</c>.</returns>
private bool IsAboveUpShiftCurve(uint gear, NewtonMeter inTorque, PerSecond inEngineSpeed,
bool torqueConverterLocked)
{
// downshift not possible
if (!_gearbox.TorqueConverterLocked && gear == 1) {
return false;
}
if (IsBelowDownShiftCurve(gear, inTorque, inAngularVelocity)) {
Downshift(absTime, gear);
return true;
}
var shiftPolygon = torqueConverterLocked
? ModelData.Gears[gear].ShiftPolygon
: ModelData.Gears[gear].TorqueConverterShiftPolygon;
return false;
return gear < ModelData.Gears.Keys.Max() && shiftPolygon.IsAboveUpshiftCurve(inTorque, inEngineSpeed);
}
public uint Engage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity)
private void Upshift(Second absTime, uint gear)
{
if (_nextGear.AbsTime != null && _nextGear.AbsTime.IsEqual(absTime)) {
_gearbox.TorqueConverterLocked = _nextGear.TorqueConverterLocked;
_gearbox.Disengaged = _nextGear.Disengaged;
_nextGear.AbsTime = null;
return _nextGear.Gear;
// C -> L: switch from torque converter to locked gear
if (!_gearbox.TorqueConverterLocked && ModelData.Gears[gear].HasLockedGear) {
_nextGear.SetState(absTime, disengaged: false, gear: gear, tcLocked: true);
return;
}
_nextGear.AbsTime = null;
return _gearbox.Gear;
}
public void Disengage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outEngineSpeed)
{
throw new System.NotImplementedException("AT Shift Strategy does not support disengaging.");
// L -> L+1
// C -> C+1
if (ModelData.Gears.ContainsKey(gear + 1)) {
_nextGear.SetState(absTime, disengaged: false, gear: gear + 1, tcLocked: _gearbox.TorqueConverterLocked);
return;
}
// C -> L+1 -- not allowed!!
throw new VectoSimulationException(
"ShiftStrategy wanted to shift up, but current gear has active torque converter (C) but no locked gear (no L) and shifting directly to (L) is not allowed.");
}
public IGearbox Gearbox
[SuppressMessage("ReSharper", "UnusedParameter.Local")]
private bool CheckDownshift(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity,
NewtonMeter inTorque, PerSecond inAngularVelocity, uint gear, Second lastShiftTime)
{
get { return _gearbox; }
set
{
var myGearbox = value as ATGearbox;
if (myGearbox == null) {
throw new VectoException("AT Shift strategy can only handle AT gearboxes, given: {0}",
value.GetType());
}
_gearbox = myGearbox;
var shiftTimeReached = (absTime - lastShiftTime).IsGreaterOrEqual(ModelData.ShiftTime);
if (!shiftTimeReached)
return false;
if (IsBelowDownShiftCurve(gear, inTorque, inAngularVelocity)) {
Downshift(absTime, gear);
return true;
}
}
public GearInfo NextGear
{
get { return new GearInfo() { Gear = _nextGear.Gear, TorqueConverterLocked = _nextGear.TorqueConverterLocked }; }
return false;
}
/// <summary>
/// Tests if the operating point is below the down-shift curve (=outside of shift curve).
/// Tests if the operating point is below (left of) the down-shift curve.
/// </summary>
/// <param name="gear">The gear.</param>
/// <param name="inTorque">The in torque.</param>
......@@ -298,26 +317,27 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
/// <returns><c>true</c> if the operating point is below the down-shift curv; otherwise, <c>false</c>.</returns>
private bool IsBelowDownShiftCurve(uint gear, NewtonMeter inTorque, PerSecond inEngineSpeed)
{
return gear > 1 && _data.Gears[gear].ShiftPolygon.IsBelowDownshiftCurve(inTorque, inEngineSpeed);
return gear > 1 && ModelData.Gears[gear].ShiftPolygon.IsBelowDownshiftCurve(inTorque, inEngineSpeed);
}
/// <summary>
/// Tests if the operating point is above the up-shift curve (=outside of shift curve).
/// </summary>
/// <param name="gear">The gear.</param>
/// <param name="inTorque">The in torque.</param>
/// <param name="inEngineSpeed">The in engine speed.</param>
/// <param name="torqueConverterLocked">if true, the regular shift polygon is used, otherwise the shift polygon for the torque converter is used</param>
/// <returns><c>true</c> if the operating point is above the up-shift curve; otherwise, <c>false</c>.</returns>
private bool IsAboveUpShiftCurve(uint gear, NewtonMeter inTorque, PerSecond inEngineSpeed,
bool torqueConverterLocked)
private void Downshift(Second absTime, uint gear)
{
if (torqueConverterLocked) {
return gear < _data.Gears.Keys.Max() &&
_data.Gears[gear].ShiftPolygon.IsAboveUpshiftCurve(inTorque, inEngineSpeed);
// L -> C
if (_gearbox.TorqueConverterLocked && ModelData.Gears[gear].HasTorqueConverter) {
_nextGear.SetState(absTime, disengaged: false, gear: gear, tcLocked: false);
return;
}
// L -> L-1
// C -> C-1
if (ModelData.Gears.ContainsKey(gear - 1)) {
_nextGear.SetState(absTime, disengaged: false, gear: gear - 1, tcLocked: _gearbox.TorqueConverterLocked);
return;
}
return gear < _data.Gears.Keys.Max() &&
_data.Gears[gear].TorqueConverterShiftPolygon.IsAboveUpshiftCurve(inTorque, inEngineSpeed);
// L -> 0 -- not allowed!!
throw new VectoSimulationException(
"ShiftStrategy wanted to shift down but current gear is locked (L) and has no torque converter (C) and disenganging directly from (L) is not allowed.");
}
private class NextGearState
......
using TUGraz.VectoCommon.Exceptions;
using TUGraz.VectoCommon.Models;
using TUGraz.VectoCommon.Utils;
using TUGraz.VectoCore.Configuration;
using TUGraz.VectoCore.Models.Simulation.DataBus;
using TUGraz.VectoCore.Models.SimulationComponent.Data;
namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
{
public abstract class BaseShiftStrategy : LoggingObject, IShiftStrategy
{
protected readonly IDataBus DataBus;
protected readonly GearboxData ModelData;
protected BaseShiftStrategy(GearboxData data, IDataBus dataBus)
{
ModelData = data;
DataBus = dataBus;
}
public abstract bool ShiftRequired(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity,
NewtonMeter inTorque,
PerSecond inAngularVelocity, uint gear, Second lastShiftTime);
public abstract uint InitGear(Second absTime, Second dt, NewtonMeter torque, PerSecond outAngularVelocity);
public abstract uint Engage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity);
public abstract void Disengage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outEngineSpeed);
public abstract IGearbox Gearbox { get; set; }
public abstract GearInfo NextGear { get; }
protected MeterPerSquareSecond EstimateAccelerationForGear(uint gear, PerSecond gbxAngularVelocityOut)
{
if (gear == 0 || gear > ModelData.Gears.Count) {
throw new VectoSimulationException("invalid gear: {0}", gear);
}
var vehicleSpeed = DataBus.VehicleSpeed;
var nextEngineSpeed = gbxAngularVelocityOut * ModelData.Gears[gear].Ratio;
var maxEnginePower = DataBus.EngineStationaryFullPower(nextEngineSpeed);
var avgSlope =
((DataBus.CycleLookAhead(Constants.SimulationSettings.GearboxLookaheadForAccelerationEstimation).Altitude -
DataBus.Altitude) / Constants.SimulationSettings.GearboxLookaheadForAccelerationEstimation).Value().SI<Radian>();
var airDragLoss = DataBus.AirDragResistance(vehicleSpeed, vehicleSpeed) * DataBus.VehicleSpeed;
var rollResistanceLoss = DataBus.RollingResistance(avgSlope) * DataBus.VehicleSpeed;
var gearboxLoss = ModelData.Gears[gear].LossMap.GetTorqueLoss(gbxAngularVelocityOut,
maxEnginePower / nextEngineSpeed * ModelData.Gears[gear].Ratio).Value * nextEngineSpeed;
//DataBus.GearboxLoss();
var slopeLoss = DataBus.SlopeResistance(avgSlope) * DataBus.VehicleSpeed;
var axleLoss = DataBus.AxlegearLoss();
var accelerationPower = maxEnginePower - gearboxLoss - axleLoss - airDragLoss - rollResistanceLoss - slopeLoss;
var acceleration = accelerationPower / DataBus.VehicleSpeed / (DataBus.TotalMass + DataBus.ReducedMassWheels);
return acceleration.Cast<MeterPerSquareSecond>();
}
}
}
\ No newline at end of file
......@@ -56,7 +56,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
if (!gearboxModelData.Type.AutomaticTransmission()) {
return;
}
var strategy = new CycleShiftStrategy { Gearbox = this };
var strategy = new CycleShiftStrategy(ModelData, null);
TorqueConverter = new TorqueConverter(this, strategy, container, gearboxModelData.TorqueConverterData, engineInertia);
if (TorqueConverter == null) {
throw new VectoException("Torque Converter required for AT transmission!");
......@@ -378,33 +378,35 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
public bool TorqueConverterActive;
}
public class CycleShiftStrategy : IShiftStrategy
public class CycleShiftStrategy : BaseShiftStrategy
{
public bool ShiftRequired(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity,
public CycleShiftStrategy(GearboxData data, IDataBus dataBus) : base(data, dataBus) {}
public override IGearbox Gearbox { get; set; }
public override bool ShiftRequired(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity,
NewtonMeter inTorque,
PerSecond inAngularVelocity, uint gear, Second lastShiftTime)
{
return false;
}
public uint InitGear(Second absTime, Second dt, NewtonMeter torque, PerSecond outAngularVelocity)
public override uint InitGear(Second absTime, Second dt, NewtonMeter torque, PerSecond outAngularVelocity)
{
throw new System.NotImplementedException();
}
public uint Engage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity)
public override uint Engage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity)
{
throw new System.NotImplementedException();
}
public void Disengage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outEngineSpeed)
public override void Disengage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outEngineSpeed)
{
throw new System.NotImplementedException();
}
public IGearbox Gearbox { get; set; }
public GearInfo NextGear
public override GearInfo NextGear
{
get { throw new System.NotImplementedException(); }
}
......
......@@ -31,7 +31,6 @@
using TUGraz.VectoCommon.Exceptions;
using TUGraz.VectoCommon.Utils;
using TUGraz.VectoCore.Configuration;
using TUGraz.VectoCore.Models.Simulation.DataBus;
using TUGraz.VectoCore.Models.SimulationComponent.Data;
......@@ -40,35 +39,15 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
/// <summary>
/// Class ShiftStrategy is a base class for shift strategies. Implements some helper methods for checking the shift curves.
/// </summary>
public abstract class ShiftStrategy : IShiftStrategy
public abstract class ShiftStrategy : BaseShiftStrategy
{
protected IDataBus DataBus;
protected GearboxData Data;
protected Gearbox _gearbox;
protected bool SkipGears;
protected bool EarlyShiftUp;
protected Gearbox _gearbox;
protected ShiftStrategy(GearboxData data, IDataBus dataBus)
{
DataBus = dataBus;
Data = data;
}
public abstract GearInfo NextGear { get; }
public abstract uint Engage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity);
public abstract void Disengage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outEngineSpeed);
public abstract bool ShiftRequired(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity,
NewtonMeter inTorque, PerSecond inAngularSpeed, uint gear, Second lastShiftTime);
public abstract uint InitGear(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity);
protected ShiftStrategy(GearboxData data, IDataBus dataBus) : base(data, dataBus) {}
public IGearbox Gearbox
public override IGearbox Gearbox
{
get { return _gearbox; }
set
......@@ -81,36 +60,6 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
}
}
protected MeterPerSquareSecond EstimateAccelerationForGear(uint gear, PerSecond gbxAngularVelocityOut)
{
if (gear == 0 || gear > _gearbox.ModelData.Gears.Count) {
throw new VectoSimulationException("invalid gear: {0}", gear);
}
var vehicleSpeed = DataBus.VehicleSpeed;
var nextEngineSpeed = gbxAngularVelocityOut * _gearbox.ModelData.Gears[gear].Ratio;
var maxEnginePower = DataBus.EngineStationaryFullPower(nextEngineSpeed);
var avgSlope =
((DataBus.CycleLookAhead(Constants.SimulationSettings.GearboxLookaheadForAccelerationEstimation).Altitude -
DataBus.Altitude) / Constants.SimulationSettings.GearboxLookaheadForAccelerationEstimation).Value().SI<Radian>();
var airDragLoss = DataBus.AirDragResistance(vehicleSpeed, vehicleSpeed) * DataBus.VehicleSpeed;
var rollResistanceLoss = DataBus.RollingResistance(avgSlope) * DataBus.VehicleSpeed;
var gearboxLoss = _gearbox.ModelData.Gears[gear].LossMap.GetTorqueLoss(gbxAngularVelocityOut,
maxEnginePower / nextEngineSpeed * _gearbox.ModelData.Gears[gear].Ratio).Value * nextEngineSpeed;
//DataBus.GearboxLoss();
var slopeLoss = DataBus.SlopeResistance(avgSlope) * DataBus.VehicleSpeed;
var axleLoss = DataBus.AxlegearLoss();
var accelerationPower = maxEnginePower - gearboxLoss - axleLoss - airDragLoss - rollResistanceLoss - slopeLoss;
var acceleration = accelerationPower / DataBus.VehicleSpeed / (DataBus.TotalMass + DataBus.ReducedMassWheels);
return acceleration.Cast<MeterPerSquareSecond>();
}
/// <summary>
/// Tests if the operating point is below the down-shift curve (=outside of shift curve).
/// </summary>
......@@ -118,12 +67,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
/// <param name="inTorque">The in torque.</param>
/// <param name="inEngineSpeed">The in engine speed.</param>
/// <returns><c>true</c> if the operating point is below the down-shift curv; otherwise, <c>false</c>.</returns>
protected virtual bool IsBelowDownShiftCurve(uint gear, NewtonMeter inTorque, PerSecond inEngineSpeed)
protected bool IsBelowDownShiftCurve(uint gear, NewtonMeter inTorque, PerSecond inEngineSpeed)
{
if (gear <= 1) {
return false;
}
return Data.Gears[gear].ShiftPolygon.IsBelowDownshiftCurve(inTorque, inEngineSpeed);
return ModelData.Gears[gear].ShiftPolygon.IsBelowDownshiftCurve(inTorque, inEngineSpeed);
}
/// <summary>
......@@ -133,12 +82,12 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
/// <param name="inTorque">The in torque.</param>
/// <param name="inEngineSpeed">The in engine speed.</param>
/// <returns><c>true</c> if the operating point is above the up-shift curve; otherwise, <c>false</c>.</returns>
protected virtual bool IsAboveUpShiftCurve(uint gear, NewtonMeter inTorque, PerSecond inEngineSpeed)
protected bool IsAboveUpShiftCurve(uint gear, NewtonMeter inTorque, PerSecond inEngineSpeed)
{
if (gear >= Data.Gears.Count) {
if (gear >= ModelData.Gears.Count) {
return false;
}
return Data.Gears[gear].ShiftPolygon.IsAboveUpshiftCurve(inTorque, inEngineSpeed);
return ModelData.Gears[gear].ShiftPolygon.IsAboveUpshiftCurve(inTorque, inEngineSpeed);
}
}
}
\ No newline at end of file
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