Skip to content

Commit e3c5ec7

Browse files
committed
Add support for ATO
1 parent 9c45a4b commit e3c5ec7

File tree

3 files changed

+83
-19
lines changed

3 files changed

+83
-19
lines changed

Source/Orts.Common/PIDController.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public void SetCoefficients(float p, float i, float d)
5151
I = i;
5252
D = d;
5353
}
54-
public void Update(float elapsedClockSeconds, float error)
54+
public void Update(float elapsedClockSeconds, float error, float offset=0)
5555
{
5656
if (!Active)
5757
{
@@ -69,7 +69,7 @@ public void Update(float elapsedClockSeconds, float error)
6969
float i_out = I * TotalError;
7070
float d_out = D * d_error;
7171

72-
Value = d_out + p_out + i_out;
72+
Value = d_out + p_out + i_out + offset;
7373
if (Value < MinValue) Value = MinValue;
7474
if (Value > MaxValue) Value = MaxValue;
7575

Source/Orts.Simulation/Common/Scripting/TrainControlSystem.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,28 @@ internal void AttachToHost(ScriptedTrainControlSystem host)
356356
/// Set dynamic brake controller to position in range [0-1].
357357
/// </summary>
358358
public Action<float> SetDynamicBrakeController;
359+
public float? ATOSetSpeedMpS
360+
{
361+
get
362+
{
363+
return Locomotive.CruiseControl?.ATOSetSpeedMpS;
364+
}
365+
set
366+
{
367+
if (Locomotive.CruiseControl != null) Locomotive.CruiseControl.ATOSetSpeedMpS = value;
368+
}
369+
}
370+
public float? ATOSetAccelerationMpSS
371+
{
372+
get
373+
{
374+
return Locomotive.CruiseControl?.ATOSetAccelerationMpSS;
375+
}
376+
set
377+
{
378+
if (Locomotive.CruiseControl != null) Locomotive.CruiseControl.ATOSetAccelerationMpSS = value;
379+
}
380+
}
359381
/// <summary>
360382
/// Cut power by pull all pantographs down.
361383
/// </summary>

Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/CruiseControl.cs

Lines changed: 59 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ public float SelectedMaxAccelerationPercent
6363
public SpeedRegulatorMode SpeedRegMode = SpeedRegulatorMode.Manual;
6464
public SpeedSelectorMode SpeedSelMode = SpeedSelectorMode.Neutral;
6565
public ControllerCruiseControlLogic CruiseControlLogic = new ControllerCruiseControlLogic();
66+
public float? ATOSetSpeedMpS;
67+
public float? ATOSetAccelerationMpSS;
6668
private float selectedSpeedMpS;
6769
public float SelectedSpeedMpS
6870
{
@@ -82,8 +84,12 @@ public float SetSpeedMpS
8284
get
8385
{
8486
if (!RestrictedRegionOdometer.Started && TimeSinceLastSelectedSpeedChangeS >= DelayBeforeSelectedSpeedUpdatingS)
87+
{
8588
CurrentSelectedSpeedMpS = SelectedSpeedMpS;
86-
return CurrentSelectedSpeedMpS;
89+
}
90+
float setSpeedMpS = CurrentSelectedSpeedMpS;
91+
if (ATOSetSpeedMpS < setSpeedMpS) setSpeedMpS = ATOSetSpeedMpS.Value;
92+
return setSpeedMpS;
8793
}
8894
}
8995
public float SetSpeedKpHOrMpH
@@ -96,8 +102,42 @@ public float SetSpeedKpHOrMpH
96102
public int SelectedNumberOfAxles = 0;
97103
public float SpeedRegulatorNominalSpeedStepMpS = 0;
98104
public float SpeedRegulatorNominalSpeedStepKpHOrMpH = 0;
99-
public float MaxAccelerationMpSS = 2;
100-
public float MaxDecelerationMpSS = 0.5f;
105+
public float maxAccelerationMpSS = 2;
106+
public float MaxAccelerationMpSS
107+
{
108+
get
109+
{
110+
if (ATOSetAccelerationMpSS > 0)
111+
{
112+
return Math.Min(ATOSetAccelerationMpSS.Value, maxAccelerationMpSS);
113+
}
114+
return maxAccelerationMpSS;
115+
}
116+
set
117+
{
118+
maxAccelerationMpSS = value;
119+
}
120+
}
121+
private float maxDecelerationMpSS = 0.5f;
122+
public float MaxDecelerationMpSS
123+
{
124+
get
125+
{
126+
if (ATOSetAccelerationMpSS < 0)
127+
{
128+
float atoDecelMpSS = -ATOSetAccelerationMpSS.Value;
129+
if (ATOSetAccelerationMpSS < -maxDecelerationMpSS && ATOSetSpeedMpS <= Math.Max(AbsWheelSpeedMpS, CurrentSelectedSpeedMpS))
130+
return atoDecelMpSS;
131+
if (ATOSetAccelerationMpSS > -maxDecelerationMpSS && Math.Max(AbsWheelSpeedMpS, ATOSetSpeedMpS.Value) < CurrentSelectedSpeedMpS)
132+
return atoDecelMpSS;
133+
}
134+
return maxDecelerationMpSS;
135+
}
136+
set
137+
{
138+
maxDecelerationMpSS = value;
139+
}
140+
}
101141
public bool UseThrottleInCombinedControl = false;
102142
public bool AntiWheelSpinEquipped = false;
103143
public float AntiWheelSpinSpeedDiffThreshold = 0.5f;
@@ -513,14 +553,14 @@ public void Update(float elapsedClockSeconds)
513553
timeFromEngineMoved = 0;
514554
reducingForce = true;
515555
}
516-
if (SpeedRegulatorOptions.Contains("engageforceonnonzerospeed") && SelectedSpeedMpS > 0 && (SpeedSelMode != SpeedSelectorMode.Parking || !ForceResetRequiredAfterBraking || (WasForceReset && SelectedMaxAccelerationPercent > 0)))
556+
if (SpeedRegulatorOptions.Contains("engageforceonnonzerospeed") && SetSpeedMpS > 0 && (SpeedSelMode != SpeedSelectorMode.Parking || !ForceResetRequiredAfterBraking || (WasForceReset && SelectedMaxAccelerationPercent > 0)))
517557
{
518558
SpeedSelMode = SpeedSelectorMode.On;
519559
SpeedRegMode = SpeedRegulatorMode.Auto;
520560
SkipThrottleDisplay = true;
521561
reducingForce = false;
522562
}
523-
else if (SpeedRegulatorOptions.Contains("engageparkingonzerospeed") && SelectedSpeedMpS == 0 && AbsWheelSpeedMpS <= (SpeedIsMph ? MpS.FromMpH(ParkingBrakeEngageSpeed) : MpS.FromKpH(ParkingBrakeEngageSpeed)) && SpeedSelMode != SpeedSelectorMode.Parking)
563+
else if (SpeedRegulatorOptions.Contains("engageparkingonzerospeed") && SetSpeedMpS == 0 && AbsWheelSpeedMpS <= (SpeedIsMph ? MpS.FromMpH(ParkingBrakeEngageSpeed) : MpS.FromKpH(ParkingBrakeEngageSpeed)) && SpeedSelMode != SpeedSelectorMode.Parking)
524564
{
525565
SpeedSelMode = SpeedSelectorMode.Parking;
526566
WasForceReset = false;
@@ -602,14 +642,14 @@ public void Update(float elapsedClockSeconds)
602642
{
603643
ThrottlePID.SetCoefficients(
604644
100 * StartReducingSpeedDelta, 1 / StartReducingSpeedDelta / 5, 0,
605-
100 / MaxThrottleAccelerationMpSS, 100 / MaxThrottleAccelerationMpSS / ThrottleFullRangeIncreaseTimeSeconds, 0
645+
100 / MaxThrottleAccelerationMpSS, 100 / MaxThrottleAccelerationMpSS / ThrottleFullRangeIncreaseTimeSeconds
606646
);
607647
}
608648
if (MaxDynamicBrakeDecelerationMpSS > 0.1f)
609649
{
610650
DynamicBrakePID.SetCoefficients(
611651
100 * StartReducingSpeedDeltaDownwards, 1 / StartReducingSpeedDeltaDownwards / 5, 0,
612-
100 / MaxDynamicBrakeDecelerationMpSS, 100 / MaxDynamicBrakeDecelerationMpSS / DynamicBrakeFullRangeIncreaseTimeSeconds, 0
652+
100 / MaxDynamicBrakeDecelerationMpSS, 100 / MaxDynamicBrakeDecelerationMpSS / DynamicBrakeFullRangeIncreaseTimeSeconds
613653
);
614654
}
615655
if (MaxTrainBrakeDecelerationMpSS > 0.1f)
@@ -1301,6 +1341,7 @@ public class SpeedAccelerationController
13011341
{
13021342
public readonly PIDController Speed;
13031343
public readonly PIDController Acceleration;
1344+
public float PAccelerationCoefficient;
13041345
public bool Active
13051346
{
13061347
get
@@ -1319,19 +1360,20 @@ public SpeedAccelerationController(PIDController speed, PIDController accel)
13191360
Speed = speed;
13201361
Acceleration = accel;
13211362
}
1322-
public void SetCoefficients(float pSpd, float iSpd, float dSpd, float pAccel, float iAccel, float dAccel)
1363+
public void SetCoefficients(float pSpd, float iSpd, float dSpd, float pAccel, float iAccel)
13231364
{
13241365
Speed.SetCoefficients(pSpd, iSpd, dSpd);
1325-
Acceleration.SetCoefficients(pAccel, iAccel, dAccel);
1366+
PAccelerationCoefficient = pAccel;
1367+
Acceleration.SetCoefficients(0, iAccel, 0);
13261368
}
1327-
public void Update(float elapsedClockSeconds, float deltaSpeed, float deltaAccel, float minPercent=0, float maxPercent=100)
1369+
public void Update(float elapsedClockSeconds, float deltaSpeed, float demandedAccel, float realAccel, float minPercent=0, float maxPercent=100)
13281370
{
13291371
Speed.MinValue = minPercent;
13301372
Speed.MaxValue = maxPercent;
13311373
Acceleration.MinValue = minPercent;
13321374
Acceleration.MaxValue = maxPercent;
13331375
Speed.Update(elapsedClockSeconds, deltaSpeed);
1334-
Acceleration.Update(elapsedClockSeconds, deltaAccel);
1376+
Acceleration.Update(elapsedClockSeconds, demandedAccel - realAccel, PAccelerationCoefficient * demandedAccel);
13351377
if (Speed.Value < Acceleration.Value)
13361378
{
13371379
// Maintain speed region
@@ -1463,7 +1505,7 @@ public void UpdateForcePID(float elapsedClockSeconds, float deltaSpeedMpS, bool
14631505
float a = AccelerationTable[(int)selectedMaxAccelerationStep - 1];
14641506
if (a > 0) maxAccelerationMpSS = Math.Min(maxAccelerationMpSS, a);
14651507
}
1466-
ThrottlePID.Update(elapsedClockSeconds, deltaSpeedMpS, maxAccelerationMpSS - RelativeAccelerationMpSS, 0, maxPercent);
1508+
ThrottlePID.Update(elapsedClockSeconds, deltaSpeedMpS, maxAccelerationMpSS, RelativeAccelerationMpSS, 0, maxPercent);
14671509
targetThrottle = ThrottlePID.Value;
14681510
}
14691511
else
@@ -1474,7 +1516,7 @@ public void UpdateForcePID(float elapsedClockSeconds, float deltaSpeedMpS, bool
14741516
{
14751517
float minPercent = TrainBrakePercent > 0 ? 50 : 0;
14761518
float maxPercent = DynamicBrakeIsSelectedForceDependant ? SelectedMaxAccelerationPercent : 100;
1477-
DynamicBrakePID.Update(elapsedClockSeconds, -deltaSpeedMpS, maxDecelerationMpSS + RelativeAccelerationMpSS, minPercent, maxPercent);
1519+
DynamicBrakePID.Update(elapsedClockSeconds, -deltaSpeedMpS, maxDecelerationMpSS, -RelativeAccelerationMpSS, minPercent, maxPercent);
14781520
targetDynamic = DynamicBrakePID.Value;
14791521
}
14801522
else
@@ -1518,10 +1560,10 @@ void UpdateTrainBrakePercent(float elapsedClockSeconds, float deltaSpeedMpS)
15181560
{
15191561
target = Math.Max((MaxDecelerationMpSS - MaxDynamicBrakeDecelerationMpSS) / MaxTrainBrakeDecelerationMpSS * 100, 0);
15201562
float accelerationDemandMpSS = (0.85f + Math.Min(CCThrottleOrDynBrakePercent / 100, 0)) * MaxDynamicBrakeDecelerationMpSS - MaxDecelerationMpSS;
1521-
TrainBrakePID.MinValue = -target;
1522-
TrainBrakePID.MaxValue = TrainBrakeMaxPercentValue-target;
1523-
TrainBrakePID.Update(elapsedClockSeconds, RelativeAccelerationMpSS - accelerationDemandMpSS);
1524-
target += TrainBrakePID.Value;
1563+
TrainBrakePID.MinValue = 0;
1564+
TrainBrakePID.MaxValue = TrainBrakeMaxPercentValue;
1565+
TrainBrakePID.Update(elapsedClockSeconds, RelativeAccelerationMpSS - accelerationDemandMpSS, target);
1566+
target = TrainBrakePID.Value;
15251567
}
15261568
if (target <= TrainBrakeMinPercentValue) TrainBrakePercent = 0;
15271569
else if (Math.Abs(TrainBrakePercent - target) > 5)

0 commit comments

Comments
 (0)