Skip to content

Commit 4216d70

Browse files
committed
Reduce floating point errors, stop use of consist durability, improve support for older superelevation parameters, simplify superelevation settings
1 parent 53e9cc6 commit 4216d70

File tree

11 files changed

+66
-81
lines changed

11 files changed

+66
-81
lines changed
Binary file not shown.

Source/Documentation/Manual/features-route.rst

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -952,20 +952,32 @@ and a third standard for 160 kph and up, the required Minimum/MaximumSpeed setti
952952
Note that the order of the ``ORTSSuperElevation`` blocks is important; they are read from top down
953953
so the slowest superelevation standard should be on top of all faster superelevation standards.
954954

955-
Open Rails also supports a simpler but less accurate way to define superelevation. It is
956-
recommended to not use this system as it does not follow the principles of real superelevation
957-
design, producing less accurate results. However, it has been retained to support prior routes.
955+
Open Rails also supports a simpler but less modern way to define superelevation based on curve
956+
radius only, without consideration for underbalance. This method may be appropriate for railroads
957+
built long in the past and will not produce the best results for modern routes.
958958
The parameter ``ORTSTrackSuperElevation`` can be added to the .trk file to define a table
959959
of superelevation values::
960960

961-
ORTSTrackSuperElevation ( x y .......... )
961+
ORTSTrackSuperElevation (
962+
x1 y1
963+
x2 y2
964+
........
965+
)
962966
963-
where x and y are a series of paired parameters specifying the curve radius in metres (x value),
964-
and the amount of superelevation in metres (y value). The statement will take as many paired
965-
values as desired. Each paired set of values must have an x and y value present. If it is desired
967+
where x and y are a series of paired parameters specifying the curve radius (default meters)
968+
(x value), and the amount of superelevation (default meters) (y value). The statement will take
969+
as many paired values as desired, as long as the radius values are in increasing order.
970+
Each paired set of values must have an x and y value present. If it is desired
966971
to 'hold' a certain value of SuperElevation for a number of different radii curves, then the same
967972
y value needs to be used for succeeding values of curve radius. Where the y value changes between
968-
curve radii, then Open Rails will extrapolate the y value between the two points.
973+
curve radii, then Open Rails will interpolate the y value between the two points.
974+
975+
Superelevation calculated using ``ORTSSuperElevation`` will generally override any values
976+
entered in ``ORTSTrackSuperElevation`` unless the ``ORTSSuperElevation`` block did not specify
977+
a value for ``MaxFreightUnderbalance`` or ``MaxPassengerUnderbalance``. If neither is given,
978+
superelevation will be replaced with the value given by ``ORTSTrackSuperElevation``, but will
979+
be adjusted to match the given values of minimum and maximum cant, precision, and runoff. This
980+
way, it is possible to represent a wide variety of superelevation configurations.
969981

970982

971983
Overhead (catenary) wire

Source/Menu/Options.Designer.cs

Lines changed: 14 additions & 30 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Source/Menu/Options.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ orderby folder.Key
325325
numericPerformanceTunerTarget.Enabled = checkPerformanceTuner.Checked;
326326

327327
// Experimental tab
328-
numericUseSuperElevation.Value = Settings.UseSuperElevation;
328+
checkUseSuperElevation.Checked = Settings.UseSuperElevation;
329329
numericSuperElevationGauge.Value = Settings.SuperElevationGauge;
330330
trackLODBias.Value = Settings.LODBias;
331331
trackLODBias_ValueChanged(null, null);
@@ -515,7 +515,7 @@ void buttonOK_Click(object sender, EventArgs e)
515515
Settings.PerformanceTunerTarget = (int)numericPerformanceTunerTarget.Value;
516516

517517
// Experimental tab
518-
Settings.UseSuperElevation = (int)numericUseSuperElevation.Value;
518+
Settings.UseSuperElevation = checkUseSuperElevation.Checked;
519519
Settings.SuperElevationGauge = (int)numericSuperElevationGauge.Value;
520520
Settings.LODBias = trackLODBias.Value;
521521
Settings.SignalLightGlow = checkSignalLightGlow.Checked;

Source/ORTS.Settings/UserSettings.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ public enum DirectXFeature
288288

289289
// Experimental settings:
290290
[Default(0)]
291-
public int UseSuperElevation { get; set; }
291+
public bool UseSuperElevation { get; set; }
292292
[Default(1435)]
293293
public int SuperElevationGauge { get; set; }
294294
[Default(0)]

Source/Orts.Formats.Msts/RouteFile.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,6 @@ public Tr_RouteFile(STFReader stf)
132132
if (RouteStart == null) throw new STFException(stf, "Missing RouteStart");
133133
if (ForestClearDistance == 0 && RemoveForestTreesFromRoads) Trace.TraceWarning("You must define also ORTSUserPreferenceForestClearDistance to avoid trees on roads");
134134
if (SuperElevation.Count <= 0) SuperElevation.Add(new SuperElevationStandard());
135-
else SuperElevationHgtpRadiusM = null; // Disable legacy superelevation system if newer system is defined
136135
}
137136

138137
public string RouteID; // ie JAPAN1 - used for TRK file and route folder name
@@ -232,12 +231,13 @@ public class SuperElevationStandard
232231
public float MaxFreightUnderbalanceM = float.PositiveInfinity;
233232
public float MaxPaxUnderbalanceM = float.PositiveInfinity;
234233
public float MinCantM = 0.0125f; // Default 1.25 cm ~ 0.5 inches
235-
public float MaxCantM = -1.0f; // Specified by user settings by default
234+
public float MaxCantM = 0.15f; // Default limit on superelevation is 15 cm ~ 6 inches
236235
public float MinSpeedMpS = MpS.FromKpH(25.0f); // Default 25 kmh ~ 15 mph
237236
public float MaxSpeedMpS = float.PositiveInfinity; // Default unlimited
238237
public float PrecisionM = 0.005f; // Default 5 mm ~ 0.2 inches
239238
public float RunoffSlope = 0.003f; // Maximum rate of change of superelevation per track length, default 0.3%
240239
public float RunoffSpeedMpS = 0.04f; // Maximum rate of change of superelevation per second, default 4 cm / sec ~ 1.5 inches / sec
240+
public bool UseLegacyCalculation = true; // Should ORTSTrackSuperElevation be used for superelevation calculations?
241241

242242
public SuperElevationStandard()
243243
{
@@ -260,6 +260,9 @@ public SuperElevationStandard(STFReader stf)
260260
new STFReader.TokenProcessor("maxrunoffspeed", () => { RunoffSpeedMpS = stf.ReadFloatBlock(STFReader.UNITS.Speed, null); }),
261261
});
262262

263+
// Disable legacy superelevation calculations if sufficient data is given
264+
if (MaxFreightUnderbalanceM <= 10.0f || MaxPaxUnderbalanceM <= 10.0f)
265+
UseLegacyCalculation = false;
263266
// Sanity check values of underbalance
264267
if (MaxFreightUnderbalanceM > 10.0f)
265268
{

Source/Orts.Simulation/Simulation/RollingStocks/TrainCar.cs

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -640,7 +640,7 @@ public Direction Direction
640640
protected float MaxUnbalancedSuperElevationM; // Maximum comfortable cant deficiency, read from MSTS Wagon File
641641
public float SuperElevationAngleRad;
642642
protected bool IsMaxSafeCurveSpeed = false; // Has equal loading speed around the curve been exceeded, ie are all the wheesl still on the track?
643-
protected float ComfortTolerance = 100.0f; // Tolerance for discomfort due to excess curve speed
643+
protected float ComfortTolerance = 1.0f; // Tolerance for discomfort due to excess curve speed
644644
public bool IsCriticalMaxSpeed = false; // Has the critical maximum speed around the curve been reached, is the wagon about to overturn?
645645
public bool IsCriticalMinSpeed = false; // Is the speed less then the minimum required for the wagon to travel around the curve
646646
protected float StartCurveResistanceFactor = 2.0f; // Set curve friction at Start = 200%
@@ -1912,9 +1912,8 @@ public virtual void UpdateCurveSpeedLimit(float elapsedClockSeconds)
19121912
if (s > MaxSafeCurveSpeedMps)
19131913
{
19141914
// Consider a tolerance so passengers won't immediately complain, should reduce overkill notifications on routes with jerky track laying
1915-
// Tolerance rapidly dies as speed excess increases, though lasts longer with consist durability set higher
19161915
// Can go negative to punish continuous speeding
1917-
ComfortTolerance -= 2.5f * (s / MaxSafeCurveSpeedMps - 1.0f) * elapsedClockSeconds;
1916+
ComfortTolerance -= 0.25f * (s / MaxSafeCurveSpeedMps - 1.0f) * elapsedClockSeconds;
19181917

19191918
if (!IsMaxSafeCurveSpeed && ComfortTolerance <= 0.0f)
19201919
{
@@ -1945,10 +1944,9 @@ public virtual void UpdateCurveSpeedLimit(float elapsedClockSeconds)
19451944
IsMaxSafeCurveSpeed = false; // reset flag for IsMaxSafeCurveSpeed reached - if speed on curve decreases
19461945
}
19471946
// Restore passenger tolerance gradually (100 seconds)
1948-
// Consist durability affects how large tolerance can grow (min 25, max 100)
1949-
ComfortTolerance += (Simulator.CurveDurability + 0.25f) * elapsedClockSeconds;
1950-
if (ComfortTolerance > 75.0f * Simulator.CurveDurability + 25.0f)
1951-
ComfortTolerance = 75.0f * Simulator.CurveDurability + 25.0f;
1947+
ComfortTolerance += elapsedClockSeconds / 100.0f;
1948+
if (ComfortTolerance > 1.0f)
1949+
ComfortTolerance = 1.0f;
19521950
}
19531951

19541952
// If speed exceeds the overturning speed, then indicated that an error condition has been reached.
@@ -2025,10 +2023,9 @@ public virtual void UpdateCurveSpeedLimit(float elapsedClockSeconds)
20252023
IsMaxSafeCurveSpeed = false; // reset flag for IsMaxEqualLoadSpeed reached
20262024

20272025
// Restore passenger tolerance gradually (100 seconds)
2028-
// Consist durability affects how large tolerance can grow
2029-
ComfortTolerance += (Simulator.CurveDurability + 0.25f) * elapsedClockSeconds;
2030-
if (ComfortTolerance > 75.0f * Simulator.CurveDurability + 25.0f)
2031-
ComfortTolerance = 75.0f * Simulator.CurveDurability + 25.0f;
2026+
ComfortTolerance += elapsedClockSeconds / 100.0f;
2027+
if (ComfortTolerance > 1.0f)
2028+
ComfortTolerance = 1.0f;
20322029
}
20332030

20342031
}
@@ -2774,7 +2771,7 @@ public void ComputePosition(Traveller traveler, bool backToFront, float elapsedT
27742771
var y = traveler.Y;
27752772
var z = traveler.Z + 2048 * (traveler.TileZ - tileZ);
27762773

2777-
Vector3 location = new Vector3(x, y, z) + traveler.CalcElevationPositionOffset(Simulator.Settings.UseSuperElevation > 0, out float r);
2774+
Vector3 location = new Vector3(x, y, z) + traveler.CalcElevationPositionOffset(Simulator.Settings.UseSuperElevation, out float r);
27782775
// This car is flipped, so flip roll direction.
27792776
r *= -1;
27802777

@@ -2806,7 +2803,7 @@ public void ComputePosition(Traveller traveler, bool backToFront, float elapsedT
28062803
var y = traveler.Y;
28072804
var z = traveler.Z + 2048 * (traveler.TileZ - tileZ);
28082805

2809-
Vector3 location = new Vector3(x, y, z) + traveler.CalcElevationPositionOffset(Simulator.Settings.UseSuperElevation > 0, out float r);
2806+
Vector3 location = new Vector3(x, y, z) + traveler.CalcElevationPositionOffset(Simulator.Settings.UseSuperElevation, out float r);
28102807

28112808
WheelAxles[k].Part.AddWheelSetLocation(1, o, location.X, location.Y, location.Z, r);
28122809
}

Source/Orts.Simulation/Simulation/Simulator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ public class Simulator
128128
public bool BreakCouplers;
129129
public int DayAmbientLight;
130130
public int CarVibrating;
131-
public int UseSuperElevation; //amount of superelevation
131+
public bool UseSuperElevation; // Whether or not visual superelevation is enabled
132132
public SuperElevation SuperElevation;
133133
public float SuperElevationGauge = 1.435f;//1.435 guage
134134
public LoadStationsPopulationFile LoadStationsPopulationFile;

0 commit comments

Comments
 (0)