Skip to content

Commit ca546dd

Browse files
committed
Fixes and improvements for unusual behavior on locomotives with 2 axles
1 parent 5edc101 commit ca546dd

File tree

3 files changed

+49
-80
lines changed

3 files changed

+49
-80
lines changed

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

Lines changed: 39 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -4516,27 +4516,9 @@ public void RepositionRearTraveller()
45164516
car.UpdateCurvePhys(traveller, new[] { 0, car.CarBogieCentreLengthM });
45174517
roll = (roll + traveller.GetVisualElevation()) / 2.0f;
45184518

4519-
// normalize across tile boundaries
4520-
while (tileX > traveller.TileX)
4521-
{
4522-
x += 2048;
4523-
--tileX;
4524-
}
4525-
while (tileX < traveller.TileX)
4526-
{
4527-
x -= 2048;
4528-
++tileX;
4529-
}
4530-
while (tileZ > traveller.TileZ)
4531-
{
4532-
z += 2048;
4533-
--tileZ;
4534-
}
4535-
while (tileZ < traveller.TileZ)
4536-
{
4537-
z -= 2048;
4538-
++tileZ;
4539-
}
4519+
// Normalize across tile boundaries
4520+
x += 2048 * (tileX - traveller.TileX);
4521+
z += 2048 * (tileZ - traveller.TileZ);
45404522

45414523
car.WorldPosition.XNAMatrix = Matrix.Identity;
45424524
if (!car.Flipped)
@@ -4546,13 +4528,19 @@ public void RepositionRearTraveller()
45464528
car.WorldPosition.XNAMatrix.M33 = -1;
45474529
}
45484530

4549-
// Position car based on MSTS position, and rotate based on superelevation
4531+
// Position car based on position of the front and rear of the car
45504532
car.WorldPosition.XNAMatrix *= Simulator.XNAMatrixFromMSTSCoordinates(traveller.X, traveller.Y, traveller.Z, x, y, z);
4533+
4534+
// Update gravity force when position is updated, but before any secondary motion is added
4535+
Vector3 fwd = car.WorldPosition.XNAMatrix.Backward;
4536+
car.GravityForceN = car.MassKG * TrainCar.GravitationalAccelerationMpS2 * fwd.Y;
4537+
car.CurrentElevationPercent = 100f * (fwd.Y / (float)Math.Sqrt(1 - fwd.Y * fwd.Y));
4538+
4539+
// Apply superelevation to car
45514540
car.WorldPosition.XNAMatrix = Matrix.CreateRotationZ((car.Flipped ? -1.0f : 1.0f) * roll) * car.WorldPosition.XNAMatrix;
45524541

45534542
// note the railcar sits 0.275meters above the track database path TODO - is this always consistent?
4554-
float railOffset = 0.275f;
4555-
car.WorldPosition.XNAMatrix.Translation += car.WorldPosition.XNAMatrix.Up * railOffset;
4543+
car.WorldPosition.XNAMatrix.Translation += car.WorldPosition.XNAMatrix.Up * 0.275f;
45564544

45574545
car.WorldPosition.TileX = traveller.TileX;
45584546
car.WorldPosition.TileZ = traveller.TileZ;
@@ -4649,27 +4637,9 @@ public void CalculatePositionOfCars(float elapsedTime, float distance)
46494637
car.UpdateCurvePhys(traveller, new[] { 0, car.CarBogieCentreLengthM });
46504638
roll = (roll + traveller.GetVisualElevation()) / 2.0f;
46514639

4652-
// normalize across tile boundaries
4653-
while (tileX > traveller.TileX)
4654-
{
4655-
x += 2048;
4656-
--tileX;
4657-
}
4658-
while (tileX < traveller.TileX)
4659-
{
4660-
x -= 2048;
4661-
++tileX;
4662-
}
4663-
while (tileZ > traveller.TileZ)
4664-
{
4665-
z += 2048;
4666-
--tileZ;
4667-
}
4668-
while (tileZ < traveller.TileZ)
4669-
{
4670-
z -= 2048;
4671-
++tileZ;
4672-
}
4640+
// Normalize across tile boundaries
4641+
x += 2048 * (tileX - traveller.TileX);
4642+
z += 2048 * (tileZ - traveller.TileZ);
46734643

46744644
car.WorldPosition.XNAMatrix = Matrix.Identity;
46754645
if (car.Flipped)
@@ -4679,20 +4649,26 @@ public void CalculatePositionOfCars(float elapsedTime, float distance)
46794649
car.WorldPosition.XNAMatrix.M33 = -1;
46804650
}
46814651

4682-
// Position car based on MSTS position, and rotate based on superelevation
4652+
// Position car based on position of the front and rear of the car
46834653
car.WorldPosition.XNAMatrix *= Simulator.XNAMatrixFromMSTSCoordinates(traveller.X, traveller.Y, traveller.Z, x, y, z);
4654+
4655+
// Update gravity force when position is updated, but before any secondary motion is added
4656+
Vector3 fwd = car.WorldPosition.XNAMatrix.Backward;
4657+
car.GravityForceN = car.MassKG * TrainCar.GravitationalAccelerationMpS2 * fwd.Y;
4658+
car.CurrentElevationPercent = 100f * (fwd.Y / (float)Math.Sqrt(1 - fwd.Y * fwd.Y));
4659+
4660+
// Apply superelevation to car
46844661
car.WorldPosition.XNAMatrix = Matrix.CreateRotationZ((car.Flipped ? -1.0f : 1.0f) * roll) * car.WorldPosition.XNAMatrix;
46854662

46864663
// note the railcar sits 0.275meters above the track database path TODO - is this always consistent?
4687-
float railOffset = 0.275f;
4688-
car.WorldPosition.XNAMatrix.Translation += car.WorldPosition.XNAMatrix.Up * railOffset;
4664+
car.WorldPosition.XNAMatrix.Translation += car.WorldPosition.XNAMatrix.Up * 0.275f;
46894665

46904666
car.WorldPosition.TileX = traveller.TileX;
46914667
car.WorldPosition.TileZ = traveller.TileZ;
46924668

46934669
traveller.Move((car.CarLengthM - car.CarBogieCentreLengthM) / 2.0f); // Move to the front of the car
46944670

4695-
car.UpdateVibration(traveller, elapsedTime, distance, SpeedMpS);
4671+
car.UpdateVibration(traveller, elapsedTime, distance);
46964672
}
46974673
length += car.CarLengthM;
46984674
// update position of container in discrete freight animations
@@ -4742,27 +4718,9 @@ public void CalculatePositionOfEOT()
47424718
car.UpdateCurvePhys(traveller, new[] { 0, car.CarBogieCentreLengthM });
47434719
roll = (roll + traveller.GetVisualElevation()) / 2.0f;
47444720

4745-
// normalize across tile boundaries
4746-
while (tileX > traveller.TileX)
4747-
{
4748-
x += 2048;
4749-
--tileX;
4750-
}
4751-
while (tileX < traveller.TileX)
4752-
{
4753-
x -= 2048;
4754-
++tileX;
4755-
}
4756-
while (tileZ > traveller.TileZ)
4757-
{
4758-
z += 2048;
4759-
--tileZ;
4760-
}
4761-
while (tileZ < traveller.TileZ)
4762-
{
4763-
z -= 2048;
4764-
++tileZ;
4765-
}
4721+
// Normalize across tile boundaries
4722+
x += 2048 * (tileX - traveller.TileX);
4723+
z += 2048 * (tileZ - traveller.TileZ);
47664724

47674725
car.WorldPosition.XNAMatrix = Matrix.Identity;
47684726
if (car.Flipped)
@@ -4772,20 +4730,26 @@ public void CalculatePositionOfEOT()
47724730
car.WorldPosition.XNAMatrix.M33 = -1;
47734731
}
47744732

4775-
// Position car based on MSTS position, and rotate based on superelevation
4733+
// Position car based on position of the front and rear of the car
47764734
car.WorldPosition.XNAMatrix *= Simulator.XNAMatrixFromMSTSCoordinates(traveller.X, traveller.Y, traveller.Z, x, y, z);
4735+
4736+
// Update gravity force when position is updated, but before any secondary motion is added
4737+
Vector3 fwd = car.WorldPosition.XNAMatrix.Backward;
4738+
car.GravityForceN = car.MassKG * TrainCar.GravitationalAccelerationMpS2 * fwd.Y;
4739+
car.CurrentElevationPercent = 100f * (fwd.Y / (float)Math.Sqrt(1 - fwd.Y * fwd.Y));
4740+
4741+
// Apply superelevation to car
47774742
car.WorldPosition.XNAMatrix = Matrix.CreateRotationZ((car.Flipped ? -1.0f : 1.0f) * roll) * car.WorldPosition.XNAMatrix;
47784743

47794744
// note the railcar sits 0.275meters above the track database path TODO - is this always consistent?
4780-
float railOffset = 0.275f;
4781-
car.WorldPosition.XNAMatrix.Translation += car.WorldPosition.XNAMatrix.Up * railOffset;
4745+
car.WorldPosition.XNAMatrix.Translation += car.WorldPosition.XNAMatrix.Up * 0.275f;
47824746

47834747
car.WorldPosition.TileX = traveller.TileX;
47844748
car.WorldPosition.TileZ = traveller.TileZ;
47854749

47864750
traveller.Move((car.CarLengthM - car.CarBogieCentreLengthM) / 2.0f); // Move to the front of the car
47874751

4788-
car.UpdateVibration(traveller, elapsedTime, distance, SpeedMpS);
4752+
car.UpdateVibration(traveller, elapsedTime, distance);
47894753
length += car.CarLengthM;
47904754
}
47914755
traveller = new Traveller(traveller, Traveller.TravellerDirection.Backward);
@@ -4821,7 +4785,7 @@ public void RecalculateRearTDBTraveller()
48214785
// advance to the front of the car
48224786
traveller.Move(car.CarLengthM);
48234787

4824-
car.UpdateVibration(traveller, elapsedTime, distance, SpeedMpS);
4788+
car.UpdateVibration(traveller, elapsedTime, distance);
48254789
length += car.CarLengthM;
48264790
}
48274791
RearTDBTraveller = new Traveller(traveller);

Source/Orts.Simulation/Simulation/RollingStocks/MSTSWagon.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,11 @@ public virtual void LoadFromWagFile(string wagFilePath)
514514

515515
if (CarBogieCentreLengthM == 0)
516516
{
517-
CarBogieCentreLengthM = (CarCouplerFaceLengthM - 4.3f);
517+
CarBogieCentreLengthM = CarCouplerFaceLengthM - 4.3f;
518+
519+
// Prevent negative values on very short train cars
520+
if (CarBogieCentreLengthM < 0)
521+
CarBogieCentreLengthM = CarLengthM * 0.65f;
518522
}
519523

520524
if (CarAirHoseLengthM == 0)

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,7 @@ public Direction Direction
647647
public bool IsCriticalMinSpeed = false; // Is the speed less then the minimum required for the wagon to travel around the curve
648648
protected float StartCurveResistanceFactor = 2.0f; // Set curve friction at Start = 200%
649649
protected float RouteSpeedMpS; // Max Route Speed Limit
650-
protected const float GravitationalAccelerationMpS2 = 9.80665f; // Acceleration due to gravity 9.80665 m/s2
650+
public const float GravitationalAccelerationMpS2 = 9.80665f; // Acceleration due to gravity 9.80665 m/s2
651651
protected int WagonNumAxles; // Number of axles on a wagon
652652
protected int InitWagonNumAxles; // Initial read of number of axles on a wagon
653653
protected float MSTSWagonNumWheels; // Number of axles on a wagon - used to read MSTS value as default
@@ -2853,7 +2853,7 @@ public void ComputePosition(Traveller traveler, bool backToFront, float elapsedT
28532853
WorldPosition.TileX = tileX;
28542854
WorldPosition.TileZ = tileZ;
28552855

2856-
UpdateVibration(traveler, elapsedTimeS, distance, speed);
2856+
UpdateVibration(traveler, elapsedTimeS, distance);
28572857

28582858
// Check bogies for any corrections needed
28592859
for (int i = 1; i < Parts.Count; i++)
@@ -2981,7 +2981,7 @@ public void UpdateCurvePhys(Traveller traveller, float[] offsets)
29812981
float MinTiltSpeedMpS = MpS.FromKpH(50.0f); // Minimum speed for tilting to be activated
29822982
float MaxTiltAngleRad = MathHelper.ToRadians(8.0f); // Maximum angle of tilting allowed
29832983

2984-
internal void UpdateVibration(Traveller traveler, float elapsedTimeS, float distanceM, float speedMpS)
2984+
internal void UpdateVibration(Traveller traveler, float elapsedTimeS, float distanceM)
29852985
{
29862986
// We need to avoid introducing any unbounded effects, so cap the elapsed time to 0.25 seconds (4FPS).
29872987
if (elapsedTimeS > 0.25f)
@@ -2990,7 +2990,8 @@ internal void UpdateVibration(Traveller traveler, float elapsedTimeS, float dist
29902990

29912991
// Don't add vibrations to train cars less than 2.5 meter in length; they're unsuitable for these calculations.
29922992
// Don't let vibrate car before EOT to avoid EOT not moving together with that car
2993-
if (CarLengthM < 2.5f || Train.EOT != null && Train.Cars.Count > 1 && Train.Cars[Train.Cars.Count - 2] == this)
2993+
// Don't add vibrations to train cars with no bogies to prevent wheels vibrating around
2994+
if (CarLengthM < 2.5f || (Train.EOT != null && Train.Cars.Count > 1 && Train.Cars[Train.Cars.Count - 2] == this) || Parts.Count <= 1)
29942995
return;
29952996
if (Simulator.Settings.CarVibratingLevel != 0)
29962997
{

0 commit comments

Comments
 (0)