Skip to content

Commit 0b4200b

Browse files
committed
Change: Abstract Acceleration logic
Cherry-pick of changes from #154
1 parent 75548dc commit 0b4200b

File tree

10 files changed

+122
-59
lines changed

10 files changed

+122
-59
lines changed

makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ create_resource_tmp = $(eval $(call resource_rule_impl, $(firstword $(subst ^, ,
302302
# OpenBve #
303303
###########
304304

305-
OPEN_BVE_FOLDERS := . Audio Game Game/Events Game/Events/EventTypes Game/ObjectManager Game/ObjectManager/AnimatedObjects Game/TrackManager Graphics Graphics/Renderer Interface OldCode Parsers Parsers/Object/BVE Parsers/Object/Generic Parsers/Object/Loksim3D Parsers/Panel Parsers/Routes Parsers/Route/BVE Parsers/Script Parsers/SoundConfiguration Parsers/Train Properties OldParsers OldParsers/BveRouteParser Simulation/TrainManager Simulation/TrainManager/Car Simulation/TrainManager/Train Simulation/World System System/Functions System/Input System/Logging System/Plugins System/Program System/Translations UserInterface
305+
OPEN_BVE_FOLDERS := . Audio Game Game/Events Game/Events/EventTypes Game/ObjectManager Game/ObjectManager/AnimatedObjects Game/TrackManager Graphics Graphics/Renderer Interface OldCode Parsers Parsers/Object/BVE Parsers/Object/Generic Parsers/Object/Loksim3D Parsers/Panel Parsers/Routes Parsers/Route/BVE Parsers/Script Parsers/SoundConfiguration Parsers/Train Properties OldParsers OldParsers/BveRouteParser Simulation/TrainManager Simulation/TrainManager/Car Simulation/TrainManager/Motor Simulation/TrainManager/Train Simulation/World System System/Functions System/Input System/Logging System/Plugins System/Program System/Translations UserInterface
306306
OPEN_BVE_FOLDERS := $(addprefix $(OPEN_BVE_ROOT)/, $(OPEN_BVE_FOLDERS))
307307
OPEN_BVE_SRC := $(filter-out "$(OPEN_BVE_ROOT)/Properties/AssemblyInfo.cs",$(patsubst %, "%", $(foreach sdir, $(OPEN_BVE_FOLDERS), $(wildcard $(sdir)/*.cs))))
308308
OPEN_BVE_DOC := $(addprefix /doc:, $(foreach sdir, $(OPEN_BVE_FOLDERS), $(wildcard $(sdir)/*.xml)))

source/OpenBVE/Game/AI.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ private void PerformDefault(TrainManager.Train Train)
320320
double decelerationCruise; /* power below this deceleration, cruise above */
321321
double decelerationStart; /* brake above this deceleration, cruise below */
322322
double decelerationStep; /* the deceleration step per brake notch */
323-
double BrakeDeceleration = Train.Cars[Train.DriverCar].Specs.BrakeDecelerationAtServiceMaximumPressure;
323+
double BrakeDeceleration = Train.Cars[Train.DriverCar].Specs.BrakeDecelerationAtServiceMaximumPressure(Train.Specs.CurrentBrakeNotch.Actual);
324324
for (int i = 0; i < Train.Cars.Length; i++)
325325
{
326326
if (Train.Cars[i].Specs.IsMotorCar)

source/OpenBVE/OldCode/TrainManager.cs

+2-42
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,6 @@ namespace OpenBve
88
/// <summary>The TrainManager is the root class containing functions to load and manage trains within the simulation world.</summary>
99
public static partial class TrainManager
1010
{
11-
12-
// cars
13-
14-
internal struct AccelerationCurve
15-
{
16-
internal double StageZeroAcceleration;
17-
internal double StageOneSpeed;
18-
internal double StageOneAcceleration;
19-
internal double StageTwoSpeed;
20-
internal double StageTwoExponent;
21-
}
2211
internal enum CarBrakeType
2312
{
2413
ElectromagneticStraightAirBrake = 0,
@@ -199,6 +188,7 @@ internal static void ParsePanelConfig(string TrainPath, System.Text.Encoding Enc
199188
Program.AppendToLogFile("Loading train panel: " + File);
200189
Panel2 = true;
201190
Panel2CfgParser.ParsePanel2Config("panel2.cfg", TrainPath, Encoding, Train, Train.DriverCar);
191+
Train.Cars[Train.DriverCar].CameraRestrictionMode = World.CameraRestrictionMode.On;
202192
World.CameraRestriction = World.CameraRestrictionMode.On;
203193
}
204194
else
@@ -208,6 +198,7 @@ internal static void ParsePanelConfig(string TrainPath, System.Text.Encoding Enc
208198
{
209199
Program.AppendToLogFile("Loading train panel: " + File);
210200
PanelCfgParser.ParsePanelConfig(TrainPath, Encoding, Train);
201+
Train.Cars[Train.DriverCar].CameraRestrictionMode = World.CameraRestrictionMode.On;
211202
World.CameraRestriction = World.CameraRestrictionMode.On;
212203
}
213204
else
@@ -228,37 +219,6 @@ internal static void ParsePanelConfig(string TrainPath, System.Text.Encoding Enc
228219
}
229220
}
230221

231-
232-
// get acceleration output
233-
internal static double GetAccelerationOutput(Train Train, int CarIndex, int CurveIndex, double Speed)
234-
{
235-
if (CurveIndex < Train.Cars[CarIndex].Specs.AccelerationCurves.Length)
236-
{
237-
double a0 = Train.Cars[CarIndex].Specs.AccelerationCurves[CurveIndex].StageZeroAcceleration;
238-
double s1 = Train.Cars[CarIndex].Specs.AccelerationCurves[CurveIndex].StageOneSpeed;
239-
double a1 = Train.Cars[CarIndex].Specs.AccelerationCurves[CurveIndex].StageOneAcceleration;
240-
double s2 = Train.Cars[CarIndex].Specs.AccelerationCurves[CurveIndex].StageTwoSpeed;
241-
double e2 = Train.Cars[CarIndex].Specs.AccelerationCurves[CurveIndex].StageTwoExponent;
242-
double f = Train.Cars[CarIndex].Specs.AccelerationCurvesMultiplier;
243-
if (Speed <= 0.0)
244-
{
245-
return f * a0;
246-
}
247-
if (Speed < s1)
248-
{
249-
double t = Speed / s1;
250-
return f * (a0 * (1.0 - t) + a1 * t);
251-
}
252-
if (Speed < s2)
253-
{
254-
return f * s1 * a1 / Speed;
255-
}
256-
return f * s1 * a1 * Math.Pow(s2, e2 - 1.0) * Math.Pow(Speed, -e2);
257-
258-
}
259-
return 0.0;
260-
}
261-
262222
// get resistance
263223
private static double GetResistance(Train Train, int CarIndex, ref Axle Axle, double Speed)
264224
{

source/OpenBVE/OpenBve.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@
196196
<DesignTime>True</DesignTime>
197197
<DependentUpon>Resources.resx</DependentUpon>
198198
</Compile>
199+
<Compile Include="Simulation\TrainManager\Motor\AccelerationCurve.cs" />
199200
<Compile Include="Simulation\TrainManager\Car\Axle.cs" />
200201
<Compile Include="Simulation\TrainManager\Car\Car.Bogie.cs" />
201202
<Compile Include="Simulation\TrainManager\Car\Car.CarSection.cs" />

source/OpenBVE/Parsers/Train/TrainDatParser.cs

+12-6
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ internal static void ParseTrainData(string FileName, System.Text.Encoding Encodi
8686
double CoefficientOfStaticFriction = 0.35;
8787
double CoefficientOfRollingResistance = 0.0025;
8888
double AerodynamicDragCoefficient = 1.1;
89-
TrainManager.AccelerationCurve[] AccelerationCurves = new TrainManager.AccelerationCurve[] { };
89+
TrainManager.BveAccelerationCurve[] AccelerationCurves = new TrainManager.BveAccelerationCurve[] { };
9090
Vector3 Driver = new Vector3();
9191
int DriverCar = 0;
9292
double MotorCarMass = 1.0, TrailerCarMass = 1.0;
@@ -123,7 +123,8 @@ internal static void ParseTrainData(string FileName, System.Text.Encoding Encodi
123123
switch (Lines[i].ToLowerInvariant()) {
124124
case "#acceleration":
125125
i++; while (i < Lines.Length && !Lines[i].StartsWith("#", StringComparison.Ordinal)) {
126-
Array.Resize<TrainManager.AccelerationCurve>(ref AccelerationCurves, n + 1);
126+
Array.Resize<TrainManager.BveAccelerationCurve>(ref AccelerationCurves, n + 1);
127+
AccelerationCurves[n] = new TrainManager.BveAccelerationCurve();
127128
string t = Lines[i] + ",";
128129
int m = 0;
129130
while (true) {
@@ -611,7 +612,10 @@ internal static void ParseTrainData(string FileName, System.Text.Encoding Encodi
611612
Train.Cars[i].Specs.BrakeType = BrakeType;
612613
Train.Cars[i].Specs.ElectropneumaticType = ElectropneumaticType;
613614
Train.Cars[i].Specs.BrakeControlSpeed = BrakeControlSpeed;
614-
Train.Cars[i].Specs.BrakeDecelerationAtServiceMaximumPressure = BrakeDeceleration;
615+
Train.Cars[i].Specs.DecelerationCurves = new TrainManager.AccelerationCurve[]
616+
{
617+
new TrainManager.BveDecelerationCurve(BrakeDeceleration),
618+
};
615619
Train.Cars[i].Specs.MotorDeceleration = MotorDeceleration;
616620
Train.Cars[i].Specs.AirBrake.AirCompressorEnabled = false;
617621
Train.Cars[i].Specs.AirBrake.AirCompressorMinimumPressure = MainReservoirMinimumPressure;
@@ -834,8 +838,11 @@ internal static void ParseTrainData(string FileName, System.Text.Encoding Encodi
834838
Train.Cars[i].Specs.AirBrake.Type = TrainManager.AirBrakeType.Main;
835839
Train.Cars[i].Specs.MassEmpty = MotorCarMass;
836840
Train.Cars[i].Specs.MassCurrent = MotorCarMass;
837-
Train.Cars[i].Specs.AccelerationCurves = AccelerationCurves;
838-
Train.Cars[i].Specs.AccelerationCurvesMultiplier = 1.0 + TrailerCars * TrailerCarMass / (MotorCars * MotorCarMass);
841+
Array.Resize(ref Train.Cars[i].Specs.AccelerationCurves, AccelerationCurves.Length);
842+
for (int j = 0; j < AccelerationCurves.Length; j++)
843+
{
844+
Train.Cars[i].Specs.AccelerationCurves[j] = AccelerationCurves[j].Clone(1.0 + TrailerCars * TrailerCarMass / (MotorCars * MotorCarMass));
845+
}
839846
Train.Cars[i].Specs.AccelerationCurveMaximum = MaximumAcceleration;
840847
switch (ReAdhesionDevice) {
841848
case 0: // type a:
@@ -884,7 +891,6 @@ internal static void ParseTrainData(string FileName, System.Text.Encoding Encodi
884891
Train.Cars[i].Specs.MassEmpty = TrailerCarMass;
885892
Train.Cars[i].Specs.MassCurrent = TrailerCarMass;
886893
Train.Cars[i].Specs.AccelerationCurves = new TrainManager.AccelerationCurve[] { };
887-
Train.Cars[i].Specs.AccelerationCurvesMultiplier = 0.0;
888894
Train.Cars[i].Specs.AccelerationCurveMaximum = 0.0;
889895
Train.Cars[i].Specs.ReAdhesionDevice.ApplicationFactor = 0.0;
890896
Train.Cars[i].Sounds.Motor.SpeedConversionFactor = 18.0;

source/OpenBVE/Simulation/TrainManager/Car/Car.Specs.cs

+15-2
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,27 @@ internal struct CarSpecs
99
/// motor
1010
internal bool IsMotorCar;
1111
internal AccelerationCurve[] AccelerationCurves;
12-
internal double AccelerationCurvesMultiplier;
12+
internal AccelerationCurve[] DecelerationCurves;
13+
14+
internal double BrakeDecelerationAtServiceMaximumPressure(int Notch)
15+
{
16+
if (Notch == 0)
17+
{
18+
return this.DecelerationCurves[0].GetAccelerationOutput(this.CurrentSpeed, 1.0);
19+
}
20+
if (this.DecelerationCurves.Length >= Notch)
21+
{
22+
return this.DecelerationCurves[Notch - 1].GetAccelerationOutput(this.CurrentSpeed, 1.0);
23+
}
24+
return this.DecelerationCurves[this.DecelerationCurves.Length - 1].GetAccelerationOutput(this.CurrentSpeed, 1.0);
25+
}
26+
1327
internal double AccelerationCurveMaximum;
1428
internal double JerkPowerUp;
1529
internal double JerkPowerDown;
1630
internal double JerkBrakeUp;
1731
internal double JerkBrakeDown;
1832
/// brake
19-
internal double BrakeDecelerationAtServiceMaximumPressure;
2033
internal double BrakeControlSpeed;
2134
internal double MotorDeceleration;
2235
/// physical properties

source/OpenBVE/Simulation/TrainManager/Car/Car.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ internal void UpdateMotorSounds(double TimeElapsed)
328328
else if (ndir == -1)
329329
{
330330
// brake
331-
double max = Specs.BrakeDecelerationAtServiceMaximumPressure;
331+
double max = Specs.BrakeDecelerationAtServiceMaximumPressure(this.baseTrain.Specs.CurrentBrakeNotch.Actual);
332332
if (max != 0.0)
333333
{
334334
double cur = -Specs.CurrentAccelerationOutput;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
using System;
2+
3+
namespace OpenBve
4+
{
5+
/// <summary>The TrainManager is the root class containing functions to load and manage trains within the simulation world.</summary>
6+
public static partial class TrainManager
7+
{
8+
/// <summary>An abstract acceleration curve</summary>
9+
internal abstract class AccelerationCurve
10+
{
11+
/// <summary>Gets the acceleration output for this curve</summary>
12+
/// <param name="Speed">The current speed</param>
13+
/// <param name="Loading">A double between 0 (Unloaded) and 1.0 (Loaded) representing the load factor</param>
14+
/// <returns>The acceleration output</returns>
15+
internal abstract double GetAccelerationOutput(double Speed, double Loading);
16+
}
17+
18+
/// <summary>Represents a BVE2 / BVE4 format Acceleration Curve</summary>
19+
internal class BveAccelerationCurve : AccelerationCurve
20+
{
21+
internal double StageZeroAcceleration;
22+
internal double StageOneSpeed;
23+
internal double StageOneAcceleration;
24+
internal double StageTwoSpeed;
25+
internal double StageTwoExponent;
26+
internal double Multiplier;
27+
28+
internal override double GetAccelerationOutput(double Speed, double Loading)
29+
{
30+
if (Speed <= 0.0)
31+
{
32+
return Multiplier * this.StageZeroAcceleration;
33+
}
34+
if (Speed < this.StageOneSpeed)
35+
{
36+
double t = Speed / this.StageOneSpeed;
37+
return Multiplier * (this.StageZeroAcceleration * (1.0 - t) + this.StageOneAcceleration * t);
38+
}
39+
if (Speed < this.StageTwoSpeed)
40+
{
41+
return Multiplier * this.StageOneSpeed * this.StageOneAcceleration / Speed;
42+
}
43+
return Multiplier * this.StageOneSpeed * this.StageOneAcceleration * Math.Pow(this.StageTwoSpeed, this.StageTwoExponent - 1.0) * Math.Pow(Speed, -this.StageTwoExponent);
44+
}
45+
46+
internal BveAccelerationCurve Clone(double multiplier)
47+
{
48+
return new BveAccelerationCurve
49+
{
50+
StageZeroAcceleration = this.StageZeroAcceleration,
51+
StageOneSpeed = this.StageOneSpeed,
52+
StageOneAcceleration = this.StageOneAcceleration,
53+
StageTwoSpeed = this.StageTwoSpeed,
54+
StageTwoExponent = this.StageTwoExponent,
55+
Multiplier = multiplier
56+
};
57+
}
58+
}
59+
60+
internal class BveDecelerationCurve : AccelerationCurve
61+
{
62+
private double MaxDecelerationOutput;
63+
internal override double GetAccelerationOutput(double Speed, double Loading)
64+
{
65+
return this.MaxDecelerationOutput;
66+
}
67+
68+
internal BveDecelerationCurve(double Deceleration)
69+
{
70+
this.MaxDecelerationOutput = Deceleration;
71+
}
72+
}
73+
}
74+
}

source/OpenBVE/Simulation/TrainManager/Train/BrakeSystem.cs

+5-5
Original file line numberDiff line numberDiff line change
@@ -400,11 +400,11 @@ private static void UpdateBrakeSystem(Train Train, int CarIndex, double TimeElap
400400
//double f = (double)Train.Specs.CurrentBrakeNotch.Actual / (double)Train.Specs.MaximumBrakeNotch;
401401
double a = Train.Cars[CarIndex].Specs.MotorDeceleration;
402402
double pr = p / Train.Cars[CarIndex].Specs.AirBrake.BrakeCylinderServiceMaximumPressure;
403-
double b = pr * Train.Cars[CarIndex].Specs.BrakeDecelerationAtServiceMaximumPressure;
403+
double b = pr * Train.Cars[CarIndex].Specs.BrakeDecelerationAtServiceMaximumPressure(Train.Specs.CurrentBrakeNotch.Actual);
404404
double d = b - a;
405405
if (d > 0.0)
406406
{
407-
p = d / Train.Cars[CarIndex].Specs.BrakeDecelerationAtServiceMaximumPressure;
407+
p = d / Train.Cars[CarIndex].Specs.BrakeDecelerationAtServiceMaximumPressure(Train.Specs.CurrentBrakeNotch.Actual);
408408
if (p > 1.0) p = 1.0;
409409
p *= Train.Cars[CarIndex].Specs.AirBrake.BrakeCylinderServiceMaximumPressure;
410410
}
@@ -507,11 +507,11 @@ private static void UpdateBrakeSystem(Train Train, int CarIndex, double TimeElap
507507
//double f = (double)Train.Specs.CurrentBrakeNotch.Actual / (double)Train.Specs.MaximumBrakeNotch;
508508
double a = Train.Cars[CarIndex].Specs.MotorDeceleration;
509509
double pr = p / Train.Cars[CarIndex].Specs.AirBrake.BrakeCylinderServiceMaximumPressure;
510-
double b = pr * Train.Cars[CarIndex].Specs.BrakeDecelerationAtServiceMaximumPressure;
510+
double b = pr * Train.Cars[CarIndex].Specs.BrakeDecelerationAtServiceMaximumPressure(Train.Specs.CurrentBrakeNotch.Actual);
511511
double d = b - a;
512512
if (d > 0.0)
513513
{
514-
p = d / Train.Cars[CarIndex].Specs.BrakeDecelerationAtServiceMaximumPressure;
514+
p = d / Train.Cars[CarIndex].Specs.BrakeDecelerationAtServiceMaximumPressure(Train.Specs.CurrentBrakeNotch.Actual);
515515
if (p > 1.0) p = 1.0;
516516
p *= Train.Cars[CarIndex].Specs.AirBrake.BrakeCylinderServiceMaximumPressure;
517517
}
@@ -662,7 +662,7 @@ private static void UpdateBrakeSystem(Train Train, int CarIndex, double TimeElap
662662
}
663663
// deceleration provided by brake
664664
double pressureratio = Train.Cars[CarIndex].Specs.AirBrake.BrakeCylinderCurrentPressure / Train.Cars[CarIndex].Specs.AirBrake.BrakeCylinderServiceMaximumPressure;
665-
DecelerationDueToBrake = pressureratio * Train.Cars[CarIndex].Specs.BrakeDecelerationAtServiceMaximumPressure;
665+
DecelerationDueToBrake = pressureratio * Train.Cars[CarIndex].Specs.BrakeDecelerationAtServiceMaximumPressure(Train.Specs.CurrentBrakeNotch.Actual);
666666
// deceleration provided by motor
667667
if (Train.Cars[CarIndex].Specs.BrakeType != CarBrakeType.AutomaticAirBrake && Math.Abs(Train.Cars[CarIndex].Specs.CurrentSpeed) >= Train.Cars[CarIndex].Specs.BrakeControlSpeed & Train.Specs.CurrentReverser.Actual != 0 & !Train.Specs.CurrentEmergencyBrake.Actual)
668668
{

source/OpenBVE/Simulation/TrainManager/Train/Train.cs

+10-1
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,16 @@ private void UpdateSpeeds(double TimeElapsed)
491491
if (Specs.CurrentReverser.Actual != 0 & Specs.CurrentPowerNotch.Actual > 0 & !Specs.CurrentHoldBrake.Actual & !Specs.CurrentEmergencyBrake.Actual)
492492
{
493493
// target acceleration
494-
a = GetAccelerationOutput(this, i, Specs.CurrentPowerNotch.Actual - 1, (double)Specs.CurrentReverser.Actual * Cars[i].Specs.CurrentSpeed);
494+
if (Specs.CurrentPowerNotch.Actual - 1 < Cars[i].Specs.AccelerationCurves.Length)
495+
{
496+
// Load factor is a constant 1.0 for anything prior to BVE5
497+
// This will need to be changed when the relevant branch is merged in
498+
a = Cars[i].Specs.AccelerationCurves[Specs.CurrentPowerNotch.Actual - 1].GetAccelerationOutput((double)Specs.CurrentReverser.Actual * Cars[i].Specs.CurrentSpeed, 1.0);
499+
}
500+
else
501+
{
502+
a = 0.0;
503+
}
495504
// readhesion device
496505
if (a > Cars[i].Specs.ReAdhesionDevice.MaximumAccelerationOutput)
497506
{

0 commit comments

Comments
 (0)