|
26 | 26 | using Orts.Simulation.RollingStocks.SubSystems.Controllers; |
27 | 27 | using ORTS.Common; |
28 | 28 | using ORTS.Scripting.Api; |
| 29 | +using static Orts.Simulation.RollingStocks.TrainCar; |
29 | 30 | namespace Orts.Simulation.RollingStocks.SubSystems |
30 | 31 | { |
31 | 32 | public class CruiseControl |
@@ -200,7 +201,12 @@ public enum SpeedSelectorMode { Parking, Neutral, On, Start } |
200 | 201 | public bool WasBraking = false; |
201 | 202 | public bool WasForceReset = true; |
202 | 203 |
|
203 | | - protected float DeltaAccelerationExponent = 0.5f; |
| 204 | + protected enum SpeedDeltaMode |
| 205 | + { |
| 206 | + Linear, |
| 207 | + Sqrt |
| 208 | + } |
| 209 | + protected SpeedDeltaMode SpeedDeltaFunctionMode = SpeedDeltaMode.Sqrt; |
204 | 210 |
|
205 | 211 | AccelerationController ThrottlePID; |
206 | 212 | AccelerationController DynamicBrakePID; |
@@ -245,7 +251,7 @@ public CruiseControl(CruiseControl other, MSTSLocomotive locomotive) |
245 | 251 | MaxForceSelectorIsDiscrete = other.MaxForceSelectorIsDiscrete; |
246 | 252 | SpeedRegulatorOptions = other.SpeedRegulatorOptions; |
247 | 253 | CruiseControlLogic = other.CruiseControlLogic; |
248 | | - DeltaAccelerationExponent = other.DeltaAccelerationExponent; |
| 254 | + SpeedDeltaFunctionMode = other.SpeedDeltaFunctionMode; |
249 | 255 | SpeedRegulatorNominalSpeedStepMpS = other.SpeedRegulatorNominalSpeedStepMpS; |
250 | 256 | MaxAccelerationMpSS = other.MaxAccelerationMpSS; |
251 | 257 | MaxDecelerationMpSS = other.MaxDecelerationMpSS; |
@@ -398,7 +404,19 @@ public void Parse(STFReader stf) |
398 | 404 | case "throttleneutralposition": ThrottleNeutralPosition = stf.ReadBoolBlock(false); break; |
399 | 405 | case "modeswitchallowedwiththrottlenotatzero": ModeSwitchAllowedWithThrottleNotAtZero = stf.ReadBoolBlock(false); break; |
400 | 406 | case "docomputenumberofaxles": DoComputeNumberOfAxles = stf.ReadBoolBlock(false); break; |
401 | | - case "deltaaccelerationexponent": DeltaAccelerationExponent = stf.ReadFloatBlock(STFReader.UNITS.Any, 1f); break; |
| 407 | + case "speeddeltafunctionmode": |
| 408 | + stf.MustMatch("("); |
| 409 | + var speedDeltaMode = stf.ReadString(); |
| 410 | + try |
| 411 | + { |
| 412 | + SpeedDeltaFunctionMode = (SpeedDeltaMode)Enum.Parse(typeof(SpeedDeltaMode), speedDeltaMode, true); |
| 413 | + } |
| 414 | + catch |
| 415 | + { |
| 416 | + STFException.TraceWarning(stf, "Skipped unknown speed delta function mode " + speedDeltaMode); |
| 417 | + SpeedDeltaFunctionMode = SpeedDeltaMode.Linear; |
| 418 | + } |
| 419 | + break; |
402 | 420 | case "options": |
403 | 421 | foreach (var speedRegulatorOption in stf.ReadStringBlock("").ToLower().Replace(" ", "").Split(',')) |
404 | 422 | { |
@@ -486,7 +504,7 @@ public void Initialize() |
486 | 504 | if (SpeedDeltaToStartAcceleratingMpS < SpeedDeltaToStopAcceleratingMpS) SpeedDeltaToStopAcceleratingMpS = SpeedDeltaToStartAcceleratingMpS; |
487 | 505 | if (SpeedDeltaToStartBrakingMpS > SpeedDeltaToStopBrakingMpS) SpeedDeltaToStopBrakingMpS = SpeedDeltaToStartBrakingMpS; |
488 | 506 |
|
489 | | - if (DeltaAccelerationExponent == 0.5f) StartReducingSpeedDeltaDownwards /= 3; |
| 507 | + if (SpeedDeltaFunctionMode == SpeedDeltaMode.Sqrt) StartReducingSpeedDeltaDownwards /= 3; |
490 | 508 |
|
491 | 509 | if (StartInAutoMode) SpeedRegMode = SpeedRegulatorMode.Auto; |
492 | 510 |
|
@@ -1239,18 +1257,14 @@ public void UpdateRequiredForce(float elapsedClockSeconds, bool tractionAllowed) |
1239 | 1257 | // However, this means that near the set speed the algorithm oscillates, since small changes in speed |
1240 | 1258 | // correspond to higher throttle demands: |
1241 | 1259 | // da/dv = -srsd / 2 / sqrt((vset-v) * srsd) which diverges when v = vset |
1242 | | - if (DeltaAccelerationExponent == 0.5f) |
| 1260 | + if (SpeedDeltaFunctionMode == SpeedDeltaMode.Sqrt) |
1243 | 1261 | demandedAccelerationMpSS = (float)-Math.Sqrt(-demandedAccelerationMpSS); |
1244 | | - else if (DeltaAccelerationExponent != 1) |
1245 | | - demandedAccelerationMpSS = (float)-Math.Pow(-demandedAccelerationMpSS, DeltaAccelerationExponent); |
1246 | 1262 | } |
1247 | 1263 | else if (deltaSpeedMpS > SpeedDeltaToStartAcceleratingMpS || (deltaSpeedMpS > SpeedDeltaToStopAcceleratingMpS && prevDemandedAccelerationMpSS > 0)) |
1248 | 1264 | { |
1249 | 1265 | demandedAccelerationMpSS = (deltaSpeedMpS - SpeedDeltaAcceleratingOffsetMpS) * StartReducingSpeedDelta; |
1250 | | - if (DeltaAccelerationExponent == 0.5f) |
| 1266 | + if (SpeedDeltaFunctionMode == SpeedDeltaMode.Sqrt) |
1251 | 1267 | demandedAccelerationMpSS = (float)Math.Sqrt(demandedAccelerationMpSS); |
1252 | | - else if (DeltaAccelerationExponent != 1) |
1253 | | - demandedAccelerationMpSS = (float)Math.Pow(demandedAccelerationMpSS, DeltaAccelerationExponent); |
1254 | 1268 | } |
1255 | 1269 | prevDemandedAccelerationMpSS = demandedAccelerationMpSS; |
1256 | 1270 | if (ASCAccelerationMpSS > 0) |
@@ -1348,7 +1362,7 @@ void UpdateTrainBrakePercent(float elapsedClockSeconds, float demandedAccelerati |
1348 | 1362 | { |
1349 | 1363 | enabled = true; |
1350 | 1364 | } |
1351 | | - else if (SpeedDeltaToEnableTrainBrake <= 0 || demandedAccelerationMpSS <= -(float)Math.Pow(SpeedDeltaToEnableTrainBrake * StartReducingSpeedDeltaDownwards, DeltaAccelerationExponent)) |
| 1365 | + else if (SpeedDeltaToEnableTrainBrake <= 0 || demandedAccelerationMpSS <= (float)-(SpeedDeltaFunctionMode == SpeedDeltaMode.Sqrt ? Math.Sqrt(SpeedDeltaToEnableTrainBrake * StartReducingSpeedDeltaDownwards) : SpeedDeltaToEnableTrainBrake * StartReducingSpeedDeltaDownwards)) |
1352 | 1366 | { |
1353 | 1367 | // Otherwise, only enabled if dynamic brake cannot provide enough force |
1354 | 1368 | enabled = CCThrottleOrDynBrakePercent < -MinDynamicBrakePercentToEnableTrainBrake || TrainBrakePercent > 0; |
|
0 commit comments