Skip to content

Commit 918960c

Browse files
committed
Add buff force coupler angle calculation
1 parent 780b0e8 commit 918960c

File tree

1 file changed

+85
-2
lines changed
  • Source/Orts.Simulation/Simulation/RollingStocks

1 file changed

+85
-2
lines changed

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

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,10 @@ public Direction Direction
572572
public float TotalWagonLateralDerailForceN;
573573
public float LateralWindForceN;
574574
public float WagonFrontCouplerAngleRad;
575+
public float WagonFrontCouplerBuffAngleRad;
575576
public float WagonRearCouplerAngleRad;
577+
public float WagonRearCouplerBuffAngleRad;
578+
public float CarTrackPlayM = Me.FromIn(2.0f);
576579
public float AdjustedWagonFrontCouplerAngleRad;
577580
public float AdjustedWagonRearCouplerAngleRad;
578581
public float WagonFrontCouplerCurveExtM;
@@ -1196,6 +1199,10 @@ public virtual void UpdateTunnelForce()
11961199
///
11971200
/// Hence these calculations provide a "generic" approach to determining whether a car will derial or not.
11981201
///
1202+
/// Buff Coupler angle calculated from this publication: In-Train Force Limit Study by National Research Council Canada
1203+
///
1204+
/// https://nrc-publications.canada.ca/eng/view/ft/?id=8cc206d0-5dbd-42ed-9b4e-35fd9f8b8efb
1205+
///
11991206
/// </summary>
12001207

12011208
public void UpdateTrainDerailmentRisk(float elapsedClockSeconds)
@@ -1336,6 +1343,69 @@ public void UpdateTrainDerailmentRisk(float elapsedClockSeconds)
13361343
AdjustedWagonRearCouplerAngleRad = WagonRearCouplerAngleRad;
13371344
CarBehind.AdjustedWagonFrontCouplerAngleRad = CarBehind.WagonFrontCouplerAngleRad;
13381345
}
1346+
1347+
// Only process this code segment if coupler is in compression
1348+
if (CouplerForceU > 0 && CouplerSlackM < 0)
1349+
{
1350+
1351+
// Calculate Buff coupler angles. Car1 is current car, and Car2 is the car behind
1352+
// Car ahead rear coupler angle
1353+
var ThiscarCouplerlengthft = Me.ToFt(CarCouplerFaceLengthM - CarBodyLengthM) + CouplerSlackM / 2;
1354+
var CarbehindCouplerlengthft = Me.ToFt(CarBehind.CarCouplerFaceLengthM - CarBehind.CarBodyLengthM) + CouplerSlackM / 2;
1355+
var A1 = Math.Sqrt(Math.Pow(Me.ToFt(CurrentCurveRadius), 2) - Math.Pow(Me.ToFt(CarBogieCentreLengthM), 2) / 4.0f);
1356+
var A2 = (Me.ToFt(CarCouplerFaceLengthM) / 2.0f) - ThiscarCouplerlengthft;
1357+
var A = (float)Math.Atan(A1 / A2);
1358+
1359+
var B = (float)Math.Asin(2.0f * Me.ToFt(CarTrackPlayM) / Me.ToFt(CarBogieCentreLengthM));
1360+
var C1 = Math.Pow(ThiscarCouplerlengthft + CarbehindCouplerlengthft, 2);
1361+
1362+
var C2_1 = Math.Sqrt(Math.Pow(Me.ToFt(CarCouplerFaceLengthM) / 2.0f - ThiscarCouplerlengthft, 2) + Math.Pow(Me.ToFt(CurrentCurveRadius), 2) - Math.Pow(Me.ToFt(CarBogieCentreLengthM), 2) / 4.0f);
1363+
var C2_2 = (2.0f * Me.ToFt(CarTrackPlayM) * (Me.ToFt(CarCouplerFaceLengthM) / 2.0f - ThiscarCouplerlengthft)) / Me.ToFt(CarBogieCentreLengthM);
1364+
var C2 = Math.Pow((C2_1 + C2_2), 2);
1365+
1366+
var C3_1 = Math.Sqrt(Math.Pow(Me.ToFt(CarBehind.CarCouplerFaceLengthM) / 2.0f - CarbehindCouplerlengthft, 2) + Math.Pow(Me.ToFt(CurrentCurveRadius), 2) - Math.Pow(Me.ToFt(CarBehind.CarBogieCentreLengthM), 2) / 4.0f);
1367+
var C3_2 = (2.0f * Me.ToFt(CarBehind.CarTrackPlayM) * (Me.ToFt(CarBehind.CarCouplerFaceLengthM) / 2.0f - CarbehindCouplerlengthft)) / Me.ToFt(CarBehind.CarBogieCentreLengthM);
1368+
var C3 = Math.Pow((C3_1 + C3_2), 2);
1369+
1370+
var C4 = 2.0f * (ThiscarCouplerlengthft + CarbehindCouplerlengthft) * (C2_1 + C2_2);
1371+
1372+
var C = (float)Math.Acos((C1 + C2 - C3) / C4);
1373+
1374+
WagonRearCouplerBuffAngleRad = MathHelper.ToRadians(180.0f) - A + B - C;
1375+
1376+
1377+
// Trace.TraceInformation("Buff - CarId {0} Carahead {1} A {2} B {3} C {4} 180 {5}", CarID, CarAhead.WagonRearCouplerBuffAngleRad, A, B, C, MathHelper.ToRadians(180.0f));
1378+
1379+
1380+
1381+
// This car front coupler angle
1382+
var X1 = Math.Sqrt(Math.Pow(Me.ToFt(CurrentCurveRadius), 2) - Math.Pow(Me.ToFt(CarBehind.CarBogieCentreLengthM), 2) / 4.0f);
1383+
var X2 = (Me.ToFt(CarBehind.CarCouplerFaceLengthM) / 2.0f) - CarbehindCouplerlengthft;
1384+
var X = (float)Math.Atan(X1 / X2);
1385+
1386+
var Y = (float)Math.Asin(2.0f * Me.ToFt(CarBehind.CarTrackPlayM) / Me.ToFt(CarBehind.CarBogieCentreLengthM));
1387+
1388+
var Z1 = Math.Pow(ThiscarCouplerlengthft + CarbehindCouplerlengthft, 2);
1389+
var Z2_1 = Math.Sqrt(Math.Pow(Me.ToFt(CarBehind.CarCouplerFaceLengthM) / 2.0f - CarbehindCouplerlengthft, 2) + Math.Pow(Me.ToFt(CurrentCurveRadius), 2) - Math.Pow(Me.ToFt(CarBehind.CarBogieCentreLengthM), 2) / 4.0f);
1390+
var Z2_2 = (2.0f * Me.ToFt(CarBehind.CarTrackPlayM) * (Me.ToFt(CarBehind.CarCouplerFaceLengthM) / 2.0f - CarbehindCouplerlengthft)) / Me.ToFt(CarBehind.CarBogieCentreLengthM);
1391+
var Z2 = Math.Pow((Z2_1 + Z2_2), 2);
1392+
1393+
var Z3_1 = Math.Sqrt(Math.Pow(Me.ToFt(CarCouplerFaceLengthM) / 2.0f - ThiscarCouplerlengthft, 2) + Math.Pow(Me.ToFt(CurrentCurveRadius), 2) - Math.Pow(Me.ToFt(CarBogieCentreLengthM), 2) / 4.0f);
1394+
var Z3_2 = (2.0f * Me.ToFt(CarTrackPlayM) * (Me.ToFt(CarCouplerFaceLengthM) / 2.0f - ThiscarCouplerlengthft)) / Me.ToFt(CarBogieCentreLengthM);
1395+
var Z3 = Math.Pow((Z3_1 + Z3_2), 2);
1396+
1397+
var Z4 = 2.0f * (ThiscarCouplerlengthft + CarbehindCouplerlengthft) * (Z2_1 + Z2_2);
1398+
1399+
var Z = (float)Math.Acos((Z1 + Z2 - Z3) / Z4);
1400+
1401+
CarBehind.WagonFrontCouplerBuffAngleRad = MathHelper.ToRadians(180.0f) - X + Y - Z;
1402+
1403+
// Trace.TraceInformation("Buff - CarId {0} Thiscar {1} A {2} B {3} C {4} 180 {5}", CarID, WagonFrontCouplerBuffAngleRad, X, Y, Z, MathHelper.ToRadians(180.0f));
1404+
1405+
// Trace.TraceInformation("Buff - CarId {0} StringThis {1} StringBehind {2} BuffThis {3} BuffAhead {4}", CarID, WagonRearCouplerAngleRad, CarBehind.WagonFrontCouplerAngleRad, WagonRearCouplerBuffAngleRad, CarBehind.WagonFrontCouplerBuffAngleRad);
1406+
1407+
}
1408+
13391409
}
13401410
else if (CarAhead != null)
13411411
{
@@ -1344,6 +1414,9 @@ public void UpdateTrainDerailmentRisk(float elapsedClockSeconds)
13441414
AdjustedWagonRearCouplerAngleRad = 0.0f;
13451415
CarBehind.AdjustedWagonFrontCouplerAngleRad = 0.0f;
13461416
WagonRearCouplerAngleRad = 0;
1417+
WagonFrontCouplerAngleRad = 0;
1418+
WagonRearCouplerBuffAngleRad = 0;
1419+
WagonFrontCouplerBuffAngleRad = 0;
13471420
CarBehind.WagonFrontCouplerAngleRad = 0;
13481421
CarAhead.WagonRearCouplerAngleRad = 0;
13491422
}
@@ -1424,7 +1497,16 @@ public void UpdateTrainDerailmentRisk(float elapsedClockSeconds)
14241497

14251498
if (IsPlayerTrain)
14261499
{
1427-
WagonCouplerAngleDerailRad = Math.Abs(WagonRearCouplerAngleRad);
1500+
if (CouplerForceU > 0 && CouplerSlackM < 0) // If car coupler is in compression, use the buff angle
1501+
{
1502+
WagonCouplerAngleDerailRad = Math.Abs(WagonRearCouplerBuffAngleRad);
1503+
}
1504+
else // if coupler in tension, then use tension angle
1505+
{
1506+
WagonCouplerAngleDerailRad = Math.Abs(WagonRearCouplerAngleRad);
1507+
}
1508+
1509+
14281510
var numAxles = LocoNumDrvAxles + WagonNumAxles;
14291511
var numWheels = numAxles * 2;
14301512

@@ -1504,7 +1586,8 @@ public void UpdateTrainDerailmentRisk(float elapsedClockSeconds)
15041586
}
15051587
else
15061588
{
1507-
DerailmentCoefficient *= 1.4f;
1589+
// DerailmentCoefficient *= 1.4f;
1590+
DerailmentCoefficient *= 2.0f;
15081591
}
15091592

15101593
var wagonAdhesion = Train.WagonCoefficientFriction;

0 commit comments

Comments
 (0)