Skip to content

Commit 834a9d7

Browse files
committed
Automatic merge of T1.5.1-1090-g9915d87ce6 and 21 pull requests
- Pull request #891 at 9a1d6b2: Auto save - Pull request #954 at 588a3c2: Multiple Track Profiles & Superelevation Improvements - Pull request #959 at 2452cb0: Fix TrackViewer crash on big zoom value - Pull request #972 at e90a2aa: On Map window color changed switch or signal is not changed - Pull request #976 at 877cc94: Increased center of gravity range - Pull request #839 at d00beb9: First phase of https://blueprints.launchpad.net/or/+spec/additional-cruise-control-parameters - Pull request #882 at 8f695a4: Blueprint/train car operations UI window - Pull request #892 at 1f5ba4c: Signal Function OPP_SIG_ID_TRAINPATH - Pull request #922 at a3bc9e7: Autopilot for timetable mode - Pull request #953 at a519452: Fix Lights Crash on Corrupt Shapes - Pull request #962 at 46d0472: Fix pantographs on unpowered cars - Pull request #970 at 6fa5eed: feat: Remove unnecessary Windows.Forms usage - Pull request #973 at c35be87: fix: Using singular target framework to allow for different platforms across different projects - Pull request #974 at 5faea6f: Bug fix for https://bugs.launchpad.net/or/+bug/2076034 Doors remain open in AI trains - Pull request #977 at a30c659: adds cache for SD files - Pull request #978 at 91f3ee8: fix: adds MilepostUnitsMiles to Manual - Pull request #900 at c27f32d: DMI updates - Pull request #903 at 4a4b032: Downloading route content (Github, zip) - Pull request #799 at dfc715e: Consolidated wind simulation - Pull request #876 at f92de76: docs: add source for documents previously on website to source Documentation folder - Pull request #952 at 8347095: Investigation - Pulsing graphics
23 parents 088bb18 + 9915d87 + 9a1d6b2 + 588a3c2 + 2452cb0 + e90a2aa + 877cc94 + d00beb9 + 8f695a4 + 1f5ba4c + a3bc9e7 + a519452 + 46d0472 + 6fa5eed + c35be87 + 5faea6f + a30c659 + 91f3ee8 + c27f32d + 4a4b032 + dfc715e + f92de76 + 8347095 commit 834a9d7

File tree

12 files changed

+530
-369
lines changed

12 files changed

+530
-369
lines changed
Binary file not shown.

Source/Orts.Formats.Msts/RouteFile.cs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,8 @@ public string ENVFileName(SeasonType seasonType, WeatherType weatherType)
228228

229229
public class SuperElevationStandard
230230
{
231-
public float MaxFreightUnderbalanceM = 0.05f; // Default 5 cm ~ 2 inches
232-
public float MaxPaxUnderbalanceM = 0.075f; // Default 7.5 cm ~ 3 inches
231+
public float MaxFreightUnderbalanceM = float.PositiveInfinity;
232+
public float MaxPaxUnderbalanceM = float.PositiveInfinity;
233233
public float MinCantM = 0.0125f; // Default 1.25 cm ~ 0.5 inches
234234
public float MaxCantM = -1.0f; // Specified by user settings by default
235235
public float MinSpeedMpS = MpS.FromKpH(25.0f); // Default 25 kmh ~ 15 mph
@@ -241,6 +241,8 @@ public class SuperElevationStandard
241241
public SuperElevationStandard()
242242
{
243243
// Initialize new instance with default values
244+
MaxFreightUnderbalanceM = 0.05f; // Default 5 cm ~ 2 inches
245+
MaxPaxUnderbalanceM = 0.075f; // Default 7.5 cm ~ 3 inches
244246
}
245247
public SuperElevationStandard(STFReader stf)
246248
{
@@ -256,6 +258,21 @@ public SuperElevationStandard(STFReader stf)
256258
new STFReader.TokenProcessor("maxrunoffslope", () => { RunoffSlope = stf.ReadFloatBlock(STFReader.UNITS.None, null); }),
257259
new STFReader.TokenProcessor("maxrunoffspeed", () => { RunoffSpeedMpS = stf.ReadFloatBlock(STFReader.UNITS.Speed, null); }),
258260
});
261+
262+
// Sanity check values of underbalance
263+
if (MaxFreightUnderbalanceM > 10.0f)
264+
{
265+
if (MaxPaxUnderbalanceM > 10.0f)
266+
{
267+
// Neither underbalance has been defined
268+
MaxFreightUnderbalanceM = 0.05f; // Default 5 cm ~ 2 inches
269+
MaxPaxUnderbalanceM = 0.075f; // Default 7.5 cm ~ 3 inches
270+
}
271+
else // Only passenger was defined
272+
MaxFreightUnderbalanceM = MaxPaxUnderbalanceM;
273+
}
274+
else if (MaxPaxUnderbalanceM > 10.0f) // Only freight was defined
275+
MaxPaxUnderbalanceM = MaxFreightUnderbalanceM;
259276
}
260277
}
261278

Source/Orts.Formats.Msts/TrackDatabaseFile.cs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -785,18 +785,21 @@ public class TrVectorSection
785785
public int WFNameX { get; set; }
786786
/// <summary>The TileZ in the WorldFile</summary>
787787
public int WFNameZ { get; set; }
788-
/// <summary>The superelevation at the start,
789-
/// negative number will apply no visual superelevation but retains physics superelevation</summary>
790-
public float StartElevM { get; set; }
791-
/// <summary>The superelevation at the midpoint,
792-
/// negative number will apply no visual superelevation but retains physics superelevation</summary>
793-
public float MidElevM { get; set; }
794-
/// <summary>The superelevation at the end,
795-
/// negative number will apply no visual superelevation but retains physics superelevation</summary>
796-
public float EndElevM { get; set; }
788+
789+
/// <summary>Interpolator storing the amount of physics superelevation in meters vs distance along
790+
/// the track section normalized from 0 to 1.</summary>
791+
public Interpolator PhysElevTable;
792+
793+
/// <summary>Interpolator storing the angle of visual superelevation in radians vs distance along
794+
/// the track section normalized from 0 to 1.</summary>
795+
public Interpolator VisElevTable;
797796
/// <summary>Nominal amount of superelevation based on speed and radius.
798797
/// Actual superelevation used will depend on adjacent curves and superelevation settings.</summary>
799798
public float NomElevM { get; set; } = -1.0f;
799+
/// <summary>Inward/outward offset from the centerline of the track about which this track section
800+
/// is rotated during superelevation.
801+
/// 0 = centered, positive = centerline moves to inside of curve, negative = centerline moves to outside of curve</summary>
802+
public float ElevOffsetM { get; set; } = 0.0f;
800803
/// <summary>The index of the superelevation track profile suitable for this section</summary>
801804
public int TRPIndex { get; set; } = -1;
802805

Source/Orts.Formats.OR/AETraveller.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,8 +1141,7 @@ public float GetCurrentCurveRadius()
11411141
}
11421142
else if (ts.SectionCurve != null)
11431143
{
1144-
float maxv = tvs.MidElevM;
1145-
maxv = 0.14f * speed / 40f;//max 8 degree
1144+
float maxv = 0.14f * speed / 40f;//max 8 degree
11461145
//maxv *= speed / 40f;
11471146
//if (maxv.AlmostEqual(0f, 0.001f)) maxv = 0.02f; //short curve, add some effect anyway
11481147
var sign = -Math.Sign(ts.SectionCurve.Angle);

Source/Orts.Simulation/Simulation/Physics/Train.cs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4507,8 +4507,10 @@ public void RepositionRearTraveller()
45074507
var z = traveller.Z;
45084508

45094509
// Update car's curve radius and superelevation based on bogie position and move traveller to front bogie
4510-
// Outputs rotation angle for superelevation, used below
4511-
car.UpdateCurveData(traveller, new[] { 0, car.CarBogieCentreLengthM }, out float roll);
4510+
// Also determine roll angle for superelevation by averaging both bogies
4511+
float roll = traveller.GetVisualElevation();
4512+
car.UpdateCurvePhys(traveller, new[] { 0, car.CarBogieCentreLengthM });
4513+
roll = (roll + traveller.GetVisualElevation()) / 2.0f;
45124514

45134515
// normalize across tile boundaries
45144516
while (tileX > traveller.TileX)
@@ -4639,7 +4641,9 @@ public void CalculatePositionOfCars(float elapsedTime, float distance)
46394641

46404642
// Update car's curve radius and superelevation based on bogie position and move traveller to front bogie
46414643
// Outputs rotation angle for superelevation, used below
4642-
car.UpdateCurveData(traveller, new[] {0, car.CarBogieCentreLengthM}, out float roll);
4644+
float roll = traveller.GetVisualElevation();
4645+
car.UpdateCurvePhys(traveller, new[] { 0, car.CarBogieCentreLengthM });
4646+
roll = (roll + traveller.GetVisualElevation()) / 2.0f;
46434647

46444648
// normalize across tile boundaries
46454649
while (tileX > traveller.TileX)
@@ -4730,7 +4734,9 @@ public void CalculatePositionOfEOT()
47304734

47314735
// Update car's curve radius and superelevation based on bogie position and move traveller to front bogie
47324736
// Outputs rotation angle for superelevation, used below
4733-
car.UpdateCurveData(traveller, new[] { 0, car.CarBogieCentreLengthM }, out float roll);
4737+
float roll = traveller.GetVisualElevation();
4738+
car.UpdateCurvePhys(traveller, new[] { 0, car.CarBogieCentreLengthM });
4739+
roll = (roll + traveller.GetVisualElevation()) / 2.0f;
47344740

47354741
// normalize across tile boundaries
47364742
while (tileX > traveller.TileX)

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

Lines changed: 39 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -2744,9 +2744,7 @@ protected void SetUpWheelsArticulation(int carIndex)
27442744

27452745
public void ComputePosition(Traveller traveler, bool backToFront, float elapsedTimeS, float distance, float speed)
27462746
{
2747-
// Superelevation visual roll angle, will be determined during parts update
2748-
float rollAngle;
2749-
float[] bogieRoll;
2747+
// Position of bogies relative to model center, used for determining curve physics
27502748
float[] bogieOffsets = new float[Parts.Count - 1];
27512749

27522750
for (var j = 0; j < Parts.Count; j++)
@@ -2764,7 +2762,7 @@ public void ComputePosition(Traveller traveler, bool backToFront, float elapsedT
27642762
l++;
27652763
}
27662764

2767-
bogieRoll = UpdateCurveData(new Traveller(traveler), bogieOffsets, out rollAngle);
2765+
UpdateCurvePhys(new Traveller(traveler), bogieOffsets);
27682766

27692767
o = -CarLengthM / 2 - CentreOfGravityM.Z;
27702768
for (var k = 0; k < WheelAxles.Count; k++)
@@ -2775,7 +2773,12 @@ public void ComputePosition(Traveller traveler, bool backToFront, float elapsedT
27752773
var x = traveler.X + 2048 * (traveler.TileX - tileX);
27762774
var y = traveler.Y;
27772775
var z = traveler.Z + 2048 * (traveler.TileZ - tileZ);
2778-
WheelAxles[k].Part.AddWheelSetLocation(1, o, x, y, z);
2776+
2777+
Vector3 location = new Vector3(x, y, z) + traveler.CalcElevationPositionOffset(Simulator.Settings.UseSuperElevation > 0, out float r);
2778+
// This car is flipped, so flip roll direction.
2779+
r *= -1;
2780+
2781+
WheelAxles[k].Part.AddWheelSetLocation(1, o, location.X, location.Y, location.Z, r);
27792782
}
27802783
o = CarLengthM / 2 - CentreOfGravityM.Z - o;
27812784
traveler.Move(o);
@@ -2791,7 +2794,7 @@ public void ComputePosition(Traveller traveler, bool backToFront, float elapsedT
27912794
l++;
27922795
}
27932796

2794-
bogieRoll = UpdateCurveData(new Traveller(traveler), bogieOffsets, out rollAngle);
2797+
UpdateCurvePhys(new Traveller(traveler), bogieOffsets);
27952798

27962799
o = CarLengthM / 2 - CentreOfGravityM.Z;
27972800
for (var k = WheelAxles.Count - 1; k >= 0; k--)
@@ -2802,7 +2805,10 @@ public void ComputePosition(Traveller traveler, bool backToFront, float elapsedT
28022805
var x = traveler.X + 2048 * (traveler.TileX - tileX);
28032806
var y = traveler.Y;
28042807
var z = traveler.Z + 2048 * (traveler.TileZ - tileZ);
2805-
WheelAxles[k].Part.AddWheelSetLocation(1, o, x, y, z);
2808+
2809+
Vector3 location = new Vector3(x, y, z) + traveler.CalcElevationPositionOffset(Simulator.Settings.UseSuperElevation > 0, out float r);
2810+
2811+
WheelAxles[k].Part.AddWheelSetLocation(1, o, location.X, location.Y, location.Z, r);
28062812
}
28072813
o = CarLengthM / 2 + CentreOfGravityM.Z + o;
28082814
traveler.Move(o);
@@ -2812,9 +2818,21 @@ public void ComputePosition(Traveller traveler, bool backToFront, float elapsedT
28122818
for (int i = 1; i < Parts.Count; i++)
28132819
{
28142820
TrainCarPart p = Parts[i];
2815-
p.FindCenterLine();
2816-
if (p.SumWgt > 1.5)
2821+
2822+
if (p.SumWgt > 1.5f)
2823+
{
2824+
p.FindCenterLine();
28172825
p0.AddPartLocation(1, p);
2826+
}
2827+
else if (p.SumWgt > 0.5f) // Handle edge case of single axle pony trucks
2828+
{
2829+
double d = p.OffsetM - p.SumOffset / p.SumWgt;
2830+
if (-.2 < d && d < .2)
2831+
continue;
2832+
// Add a fake "wheel" to serve as a pivot point
2833+
p.AddWheelSetLocation(1, p.OffsetM, p0.Pos[0] + p.OffsetM * p0.Dir[0], p0.Pos[1] + p.OffsetM * p0.Dir[1], p0.Pos[2] + p.OffsetM * p0.Dir[2], 0);
2834+
p.FindCenterLine();
2835+
}
28182836
}
28192837
p0.FindCenterLine();
28202838
Vector3 fwd = new Vector3(p0.Dir[0], p0.Dir[1], -p0.Dir[2]);
@@ -2832,11 +2850,11 @@ public void ComputePosition(Traveller traveler, bool backToFront, float elapsedT
28322850
m.Backward = fwd;
28332851

28342852
// Roll the car for superelevation
2835-
Matrix superelevationRoll = Matrix.CreateRotationZ(rollAngle);
2836-
m = superelevationRoll * m;
2853+
m = Matrix.CreateRotationZ(p0.Roll) * m;
28372854

28382855
// Rolling stock seems to always sit 0.275 meters above the track height
28392856
float railOffset = 0.275f;
2857+
28402858
Vector3 pos = new Vector3(p0.Pos[0], p0.Pos[1], -p0.Pos[2]);
28412859
m.Translation = pos + m.Up * railOffset;
28422860

@@ -2845,29 +2863,6 @@ public void ComputePosition(Traveller traveler, bool backToFront, float elapsedT
28452863
WorldPosition.TileZ = tileZ;
28462864

28472865
UpdatedTraveler(traveler, elapsedTimeS, distance, speed);
2848-
2849-
// Determine superelevation angle for bogies
2850-
for (int i = 1; i < Parts.Count; i++)
2851-
{
2852-
TrainCarPart p = Parts[i];
2853-
if (p.SumWgt < .5) // No wheels on this bogie, skip it
2854-
continue;
2855-
if (p.SumWgt < 1.5)
2856-
{ // single axle pony trunk
2857-
double d = p.OffsetM - p.SumOffset / p.SumWgt;
2858-
if (-.2 < d && d < .2)
2859-
continue;
2860-
// Add a fake "wheel" to serve as a pivot point
2861-
p.AddWheelSetLocation(1, p.OffsetM, p0.Pos[0] + p.OffsetM * p0.Dir[0], p0.Pos[1] + p.OffsetM * p0.Dir[1], p0.Pos[2] + p.OffsetM * p0.Dir[2]);
2862-
p.FindCenterLine();
2863-
}
2864-
2865-
// Generate superelevation rotation matrix for the bogie
2866-
if (Flipped == backToFront)
2867-
p.Rotation = Matrix.CreateRotationZ(bogieRoll[i - 1]);
2868-
else
2869-
p.Rotation = Matrix.CreateRotationZ(bogieRoll[(Parts.Count - 1) - i]);
2870-
}
28712866
}
28722867

28732868
#region Traveller-based updates
@@ -2890,47 +2885,21 @@ internal void UpdatedTraveler(Traveller traveler, float elapsedTimeS, float dist
28902885
/// This WILL move the traveller by the total amount of all the offsets.
28912886
/// Directly sets the superelevation and curve radius for car physics.
28922887
/// </summary>
2893-
/// <returns>Returns an array giving the angle of visual superelevation at each calculated point.</returns>
2894-
public float[] UpdateCurveData(Traveller traveller, float[] offsets, out float roll)
2888+
public void UpdateCurvePhys(Traveller traveller, float[] offsets)
28952889
{
2896-
roll = 0;
2897-
bool visualElevationEnabled = Simulator.Settings.UseSuperElevation > 0;
2898-
28992890
// Ensure at least one offset is given
29002891
if (offsets == null || offsets.Length <= 0)
29012892
offsets = new[] { 0.0f };
29022893

29032894
// Need to get superelevation at both ends of the car by offsetting the traveller
2904-
float[] visualElevation = traveller.GetSuperElevation(visualElevationEnabled, offsets, out float[] physicsElevation, out float[] curveRadii);
2905-
2906-
float[] angles = new float[visualElevation.Length];
2895+
traveller.GetCurveData(offsets, out float[] physicsElevation, out float[] curveRadii);
29072896

29082897
// Superelevation MUST be limited to track gauge to avoid NaN errors
29092898
SuperelevationM = Math.Min(physicsElevation.Average(), TrackGaugeM);
29102899
// Set superelevation angle used by physics system
29112900
SuperElevationAngleRad = (float)Math.Asin(SuperelevationM / TrackGaugeM);
29122901

29132902
CurrentCurveRadiusM = curveRadii.Min();
2914-
float z = visualElevation.Average();
2915-
2916-
// Determine superelevation angle for animation, assuming there is any visual elevation
2917-
if (z != 0)
2918-
{
2919-
roll = (float)Math.Asin(z / TrackGaugeM);
2920-
2921-
if (Flipped)
2922-
roll *= -1;
2923-
2924-
for (int v = 0; v < visualElevation.Length; v++)
2925-
{
2926-
angles[v] = (float)Math.Asin(visualElevation[v] / TrackGaugeM);
2927-
2928-
if (Flipped)
2929-
angles[v] *= -1;
2930-
}
2931-
}
2932-
2933-
return angles;
29342903
}
29352904
#endregion
29362905

@@ -3559,7 +3528,6 @@ public class TrainCarPart
35593528
{
35603529
public float OffsetM; // distance from center of model, positive forward
35613530
public int iMatrix; // matrix index in shape that needs to be moved
3562-
public Matrix Rotation = Matrix.Identity; // Matrix giving the roll angle of the bogie in absolute terms
35633531
// line fitting variables
35643532
public double SumWgt; // Sum of component weights
35653533
public double SumOffset; // Sum of component weights times offsets
@@ -3568,6 +3536,8 @@ public class TrainCarPart
35683536
public double[] SumPosOffset = new double[3]; // Sum of component locations [x, y, z] times offsets
35693537
public float[] Pos = new float[3]; // Position [x, y, z] of this part, calculated with y-intercept of linear regression
35703538
public float[] Dir = new float[3]; // Oritentation [x, y, z] of this part, calculated with slope of linear regression
3539+
public float SumRoll; // Sum of all roll angles of components
3540+
public float Roll; // Roll angle of this part
35713541
public bool Bogie; // True if this is a bogie
35723542
public TrainCarPart(float offset, int i)
35733543
{
@@ -3583,13 +3553,14 @@ public void InitLineFit()
35833553
SumWgt = SumOffset = SumOffsetSq = 0;
35843554
for (int i = 0; i < 3; i++)
35853555
SumPos[i] = SumPosOffset[i] = 0;
3556+
SumRoll = 0;
35863557
}
35873558

35883559
/// <summary>
35893560
/// Directly adds the 3D position values of a sub part to this part. The position
35903561
/// of sub parts will be used to derive the position of this part.
35913562
/// </summary>
3592-
public void AddWheelSetLocation(float weight, float offset, float x, float y, float z)
3563+
public void AddWheelSetLocation(float weight, float offset, float x, float y, float z, float roll)
35933564
{
35943565
SumWgt += weight;
35953566
SumOffset += weight * offset;
@@ -3600,6 +3571,7 @@ public void AddWheelSetLocation(float weight, float offset, float x, float y, fl
36003571
SumPosOffset[1] += weight * y * offset;
36013572
SumPos[2] += weight * z;
36023573
SumPosOffset[2] += weight * z * offset;
3574+
SumRoll += weight * roll;
36033575
}
36043576

36053577
/// <summary>
@@ -3616,6 +3588,7 @@ public void AddPartLocation(float weight, TrainCarPart part)
36163588
SumPos[i] += weight * position;
36173589
SumPosOffset[i] += weight * position * part.OffsetM;
36183590
}
3591+
SumRoll += weight * part.Roll;
36193592
}
36203593

36213594
/// <summary>
@@ -3655,6 +3628,8 @@ public void FindCenterLine()
36553628
Dir[i] = 0;
36563629
}
36573630
}
3631+
3632+
Roll = SumRoll / (float)SumWgt;
36583633
}
36593634
}
36603635
}

0 commit comments

Comments
 (0)