@@ -638,7 +638,7 @@ public Direction Direction
638638 protected float TrackGaugeM = 1.435f ; // Track gauge - read in MSTSWagon
639639 protected Vector3 InitialCentreOfGravityM = new Vector3 ( 0 , 1.8f , 0 ) ; // get centre of gravity - read in MSTSWagon
640640 public Vector3 CentreOfGravityM = new Vector3 ( 0 , 1.8f , 0 ) ; // get centre of gravity after adjusted for freight animation
641- public float SuperelevationM ; // Super elevation on the curve
641+ public float SuperElevationM ; // Super elevation on the curve
642642 protected float MaxUnbalancedSuperElevationM ; // Maximum comfortable cant deficiency, read from MSTS Wagon File
643643 public float SuperElevationAngleRad ;
644644 protected bool IsMaxSafeCurveSpeed = false ; // Has equal loading speed around the curve been exceeded, ie are all the wheesl still on the track?
@@ -1879,24 +1879,24 @@ public virtual void UpdateCurveSpeedLimit(float elapsedClockSeconds)
18791879 {
18801880#if DEBUG_USER_SUPERELEVATION
18811881 Trace . TraceInformation ( " ============================================= User SuperElevation (TrainCar.cs) ========================================" ) ;
1882- Trace . TraceInformation ( "CarID {0} TrackSuperElevation {1} Curve Radius {2}" , CarID , SuperelevationM , CurrentCurveRadius ) ;
1882+ Trace . TraceInformation ( "CarID {0} TrackSuperElevation {1} Curve Radius {2}" , CarID , SuperElevationM , CurrentCurveRadius ) ;
18831883#endif
18841884 float s = AbsSpeedMpS ; // speed of train
18851885
18861886 // Calulate equal wheel loading speed for current curve and superelevation - this was considered the "safe" speed to travel around a curve . In this instance the load on the both railes is evenly distributed.
18871887 // max equal load speed = SQRT ( (superelevation x gravity x curve radius) / track gauge)
1888- // SuperElevation is made up of two components = rail superelevation + the amount of sideways force that a passenger will be comfortable with. This is expressed as a figure similar to superelevation.
1888+ // Superelevation is made up of two components = rail superelevation + the amount of sideways force that a passenger will be comfortable with. This is expressed as a figure similar to superelevation.
18891889
18901890 float SpeedToleranceMpS = Me . FromMi ( pS . FrompH ( 2.5f ) ) ; // Set bandwidth tolerance for resetting notifications
18911891
18921892 // Railway companies often allow the vehicle to exceed the equal loading speed, provided that the passengers didn't feel uncomfortable, and that the car was not likely to excced the maximum critical speed
1893- float MaxSafeCurveSpeedMps = ( float ) Math . Sqrt ( ( ( SuperelevationM + MaxUnbalancedSuperElevationM ) * GravitationalAccelerationMpS2 * CurrentCurveRadiusM ) / TrackGaugeM ) ;
1893+ float MaxSafeCurveSpeedMps = ( float ) Math . Sqrt ( ( ( SuperElevationM + MaxUnbalancedSuperElevationM ) * GravitationalAccelerationMpS2 * CurrentCurveRadiusM ) / TrackGaugeM ) ;
18941894
18951895 // Calculate critical speed - indicates the speed above which stock will overturn - sum of the moments of centrifrugal force and the vertical weight of the vehicle around the CoG
18961896 // critical speed = SQRT ( (centrifrugal force x gravity x curve radius) / Vehicle weight)
18971897 // centrifrugal force = Stock Weight x factor for movement of resultant force due to superelevation.
18981898
1899- float SinTheta = SuperelevationM / TrackGaugeM ; // Definition of sine: opposite / hypotenuse = superelevation / gauge
1899+ float SinTheta = SuperElevationM / TrackGaugeM ; // Definition of sine: opposite / hypotenuse = superelevation / gauge
19001900 float CosTheta = ( float ) Math . Cos ( SuperElevationAngleRad ) ;
19011901 float HalfTrackGaugeM = TrackGaugeM / 2.0f ;
19021902
@@ -2013,7 +2013,7 @@ public virtual void UpdateCurveSpeedLimit(float elapsedClockSeconds)
20132013
20142014#if DEBUG_CURVE_SPEED
20152015 Trace . TraceInformation ( "================================== TrainCar.cs - DEBUG_CURVE_SPEED ==============================================================" ) ;
2016- Trace . TraceInformation ( "CarID {0} Curve Radius {1} Super {2} Unbalanced {3} Durability {4}" , CarID , CurrentCurveRadius , SuperelevationM , UnbalancedSuperElevationM , Simulator . CurveDurability ) ;
2016+ Trace . TraceInformation ( "CarID {0} Curve Radius {1} Super {2} Unbalanced {3} Durability {4}" , CarID , CurrentCurveRadius , SuperElevationM , UnbalancedSuperElevationM , Simulator . CurveDurability ) ;
20172017 Trace . TraceInformation ( "CoG {0}" , CentreOfGravityM ) ;
20182018 Trace . TraceInformation ( "Current Speed {0} Equal Load Speed {1} Max Safe Speed {2} Critical Max Speed {3} Critical Min Speed {4}" , MpS . ToMpH ( s ) , MpS . ToMpH ( MaxCurveEqualLoadSpeedMps ) , MpS . ToMpH ( MaxSafeCurveSpeedMps ) , MpS . ToMpH ( CriticalMaxSpeedMpS ) , MpS . ToMpH ( CriticalMinSpeedMpS ) ) ;
20192019 Trace . TraceInformation ( "IsMaxSafeSpeed {0} IsCriticalSpeed {1}" , IsMaxSafeCurveSpeed , IsCriticalSpeed ) ;
@@ -2066,7 +2066,7 @@ public virtual void UpdateCurveForce(float elapsedClockSeconds)
20662066
20672067 var speedConstant = 1.5f ;
20682068 var MToMM = 1000 ;
2069- var rspeedKgpTonne = speedConstant * Math . Abs ( ( SpeedMpS * SpeedMpS / CurrentCurveRadiusM ) - ( ( MToMM * SuperelevationM / MToMM * TrackGaugeM ) * GravitationalAccelerationMpS2 ) ) ;
2069+ var rspeedKgpTonne = speedConstant * Math . Abs ( ( SpeedMpS * SpeedMpS / CurrentCurveRadiusM ) - ( ( MToMM * SuperElevationM / MToMM * TrackGaugeM ) * GravitationalAccelerationMpS2 ) ) ;
20702070 var rSpeedWagonN = GravitationalAccelerationMpS2 * ( Kg . ToTonne ( MassKG ) * rspeedKgpTonne ) ;
20712071
20722072 CurveForceN = rBaseWagonN + rSpeedWagonN ;
@@ -2801,22 +2801,10 @@ public void ComputePosition(Traveller traveler, bool backToFront, float elapsedT
28012801 for ( int i = 1 ; i < Parts . Count ; i ++ )
28022802 {
28032803 TrainCarPart p = Parts [ i ] ;
2804-
2804+ p . FindCenterLine ( ) ;
2805+
28052806 if ( p . SumWgt > 1.5f )
2806- {
2807- p . FindCenterLine ( ) ;
28082807 p0 . AddPartLocation ( 1 , p ) ;
2809- }
2810- else if ( p . SumWgt > 0.5f ) // Handle edge case of single axle pony trucks
2811- {
2812- double d = p . OffsetM . Z - p . SumZOffset / p . SumWgt ;
2813- if ( - .2 < d && d < .2 )
2814- continue ;
2815- // Add a fake "wheel" to serve as a pivot point
2816- Vector3 pos = new Vector3 ( p0 . Pos [ 0 ] + p . OffsetM . Z * p0 . Dir [ 0 ] , p0 . Pos [ 1 ] + p . OffsetM . Z * p0 . Dir [ 1 ] , p0 . Pos [ 2 ] + p . OffsetM . Z * p0 . Dir [ 2 ] ) ;
2817- p . AddWheelSetLocation ( 1 , p . OffsetM . Z , pos , p . Roll ) ;
2818- p . FindCenterLine ( ) ;
2819- }
28202808 }
28212809 // Determine facing direction and position of train car
28222810 p0 . FindCenterLine ( ) ;
@@ -2856,7 +2844,7 @@ public void ComputePosition(Traveller traveler, bool backToFront, float elapsedT
28562844 m = rollMat * m ;
28572845 }
28582846
2859- SuperelevationInverseMatrix = Matrix . Invert ( rollMat ) ;
2847+ SuperElevationInverseMatrix = Matrix . Invert ( rollMat ) ;
28602848
28612849 // Set position of train car
28622850 m . Translation += new Vector3 ( p0 . Pos [ 0 ] , p0 . Pos [ 1 ] , - p0 . Pos [ 2 ] ) ;
@@ -2866,6 +2854,23 @@ public void ComputePosition(Traveller traveler, bool backToFront, float elapsedT
28662854 WorldPosition . TileZ = tileZ ;
28672855
28682856 UpdateVibration ( traveler , elapsedTimeS , distance , speed ) ;
2857+
2858+ // Check bogies for any corrections needed
2859+ for ( int i = 1 ; i < Parts . Count ; i ++ )
2860+ {
2861+ TrainCarPart p = Parts [ i ] ;
2862+
2863+ if ( p . SumWgt < 1.5f && p . SumWgt > 0.5f ) // Handle edge case of single axle pony trucks
2864+ {
2865+ double d = p . OffsetM . Z - p . SumZOffset / p . SumWgt ;
2866+ if ( - .2 < d && d < .2 )
2867+ continue ;
2868+ // Add a fake "wheel" to serve as a pivot point
2869+ Vector3 pos = new Vector3 ( p0 . Pos [ 0 ] + p . OffsetM . Z * p0 . Dir [ 0 ] , p0 . Pos [ 1 ] + p . OffsetM . Z * p0 . Dir [ 1 ] , p0 . Pos [ 2 ] + p . OffsetM . Z * p0 . Dir [ 2 ] ) ;
2870+ p . AddWheelSetLocation ( 1 , p . OffsetM . Z , pos , p . Roll ) ;
2871+ p . FindCenterLine ( ) ;
2872+ }
2873+ }
28692874 }
28702875
28712876 #region Traveller-based updates
@@ -2898,7 +2903,7 @@ internal void UpdateTilting(Traveller traveller, float elapsedTimeS, float spee
28982903 }
28992904 #endregion
29002905
2901- #region Super-elevation
2906+ #region SuperElevation
29022907 /// <summary>
29032908 /// Determines the curve situation (superelevation and radius) of the train car, given a
29042909 /// traveller to move over an array of offsets to average out the curve across.
@@ -2915,9 +2920,9 @@ public void UpdateCurvePhys(Traveller traveller, float[] offsets)
29152920 traveller . GetCurveData ( offsets , out float [ ] physicsElevation , out float [ ] curveRadii ) ;
29162921
29172922 // Superelevation MUST be limited to track gauge to avoid NaN errors
2918- SuperelevationM = Math . Min ( physicsElevation . Average ( ) , TrackGaugeM ) ;
2923+ SuperElevationM = Math . Min ( physicsElevation . Average ( ) , TrackGaugeM ) ;
29192924 // Set superelevation angle used by physics system
2920- SuperElevationAngleRad = ( float ) Math . Asin ( SuperelevationM / TrackGaugeM ) ;
2925+ SuperElevationAngleRad = ( float ) Math . Asin ( SuperElevationM / TrackGaugeM ) ;
29212926
29222927 CurrentCurveRadiusM = curveRadii . Average ( ) ;
29232928 // Straight track has a "radius" of infinity, but rest of code expects straight to have a "radius" of 0
@@ -2928,7 +2933,7 @@ public void UpdateCurvePhys(Traveller traveller, float[] offsets)
29282933
29292934 #region Vibration and tilting
29302935 public Matrix VibrationInverseMatrix = Matrix . Identity ;
2931- public Matrix SuperelevationInverseMatrix = Matrix . Identity ;
2936+ public Matrix SuperElevationInverseMatrix = Matrix . Identity ;
29322937
29332938 // https://en.wikipedia.org/wiki/Newton%27s_laws_of_motion#Newton.27s_2nd_Law
29342939 // Let F be the force in N
0 commit comments