Skip to content

Commit acb86f8

Browse files
authored
Merge pull request #456 from peternewell/air-hose-animation#2
Further adjustment to airhose movement https://blueprints.launchpad.net/or/+spec/advanced-coupler-refinements
2 parents dfc74d6 + a4b3c4e commit acb86f8

File tree

3 files changed

+57
-43
lines changed

3 files changed

+57
-43
lines changed

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

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -477,14 +477,9 @@ public virtual void LoadFromWagFile(string wagFilePath)
477477

478478
var couplerlength = ((CarCouplerFaceLengthM - CarBodyLengthM) / 2) + 0.1f; // coupler length at rest, allow 0.1m also for slack
479479

480-
if (CarAirHoseLengthM < couplerlength)
480+
if (CarAirHoseHorizontalLengthM == 0)
481481
{
482-
CarCouplerFaceLengthM = CarBodyLengthM + (0.4f * 2.0f); // Assume a coupler length of 400mm at each end and add to car body length
483-
484-
if (Simulator.Settings.VerboseConfigurationMessages)
485-
{
486-
Trace.TraceInformation("Coupler length exceeded brake air hose length, so ORTSLengthCouplerFace decreased to {0}", CarCouplerFaceLengthM);
487-
}
482+
CarAirHoseHorizontalLengthM = 0.3862f; // 15.2 inches
488483
}
489484

490485
// Ensure Drive Axles is set to a default if no OR value added to WAG file
@@ -1018,6 +1013,7 @@ public virtual void Parse(string lowercasetoken, STFReader stf)
10181013
case "wagon(ortslengthbogiecentre": CarBogieCentreLengthM = stf.ReadFloatBlock(STFReader.UNITS.Distance, null); break;
10191014
case "wagon(ortslengthcarbody": CarBodyLengthM = stf.ReadFloatBlock(STFReader.UNITS.Distance, null); break;
10201015
case "wagon(ortslengthairhose": CarAirHoseLengthM = stf.ReadFloatBlock(STFReader.UNITS.Distance, null); break;
1016+
case "wagon(ortshorizontallengthairhose": CarAirHoseHorizontalLengthM = stf.ReadFloatBlock(STFReader.UNITS.Distance, null); break;
10211017
case "wagon(ortslengthcouplerface": CarCouplerFaceLengthM = stf.ReadFloatBlock(STFReader.UNITS.Distance, null); break;
10221018
case "wagon(ortstrackgauge":
10231019
stf.MustMatch("(");
@@ -1475,6 +1471,7 @@ public virtual void Copy(MSTSWagon copy)
14751471
CarBodyLengthM = copy.CarBodyLengthM;
14761472
CarCouplerFaceLengthM = copy.CarCouplerFaceLengthM;
14771473
CarAirHoseLengthM = copy.CarAirHoseLengthM;
1474+
CarAirHoseHorizontalLengthM = copy.CarAirHoseHorizontalLengthM;
14781475
AuxTenderWaterMassKG = copy.AuxTenderWaterMassKG;
14791476
TenderWagonMaxCoalMassKG = copy.TenderWagonMaxCoalMassKG;
14801477
TenderWagonMaxWaterMassKG = copy.TenderWagonMaxWaterMassKG;

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

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,6 @@ public static Interpolator SteamHeatBoilerFuelUsageGalukpH()
196196
public float CarBodyLengthM;
197197
public float CarCouplerFaceLengthM;
198198
public float DerailmentCoefficient;
199-
public float CarAirHoseLengthM;
200199

201200
public float MaxHandbrakeForceN;
202201
public float MaxBrakeForceN = 89e3f;
@@ -251,8 +250,13 @@ public static Interpolator SteamHeatBoilerFuelUsageGalukpH()
251250

252251
public float FrontAirHoseHeightAdjustmentM;
253252
public float RearAirHoseHeightAdjustmentM;
254-
public float FrontAirHoseAngleAdjustmentRad;
255-
public float RearAirHoseAngleAdjustmentRad;
253+
public float FrontAirHoseYAngleAdjustmentRad;
254+
public float FrontAirHoseZAngleAdjustmentRad;
255+
public float RearAirHoseYAngleAdjustmentRad;
256+
public float RearAirHoseZAngleAdjustmentRad;
257+
258+
public float CarAirHoseLengthM;
259+
public float CarAirHoseHorizontalLengthM;
256260

257261
// Used to calculate Carriage Steam Heat Loss
258262
public const float BogieHeightM = 1.06f; // Height reduced by 1.06m to allow for bogies, etc
@@ -1322,21 +1326,26 @@ public void UpdateTrainDerailmentRisk()
13221326
}
13231327
}
13241328

1325-
// Calculate airhose angles and height
1326-
var rearairhoseheightadjustmentreferenceM = (float)Math.Sqrt((float)Math.Pow(CarAirHoseLengthM, 2) - (float)Math.Pow(CouplerDistanceThisCarM, 2));
1327-
var frontairhoseheightadjustmentreferenceM = (float)Math.Sqrt((float)Math.Pow(CarAirHoseLengthM, 2) - (float)Math.Pow(CouplerDistanceBehindCarM, 2));
1329+
// Calculate airhose angles and height adjustment values for the air hose. Firstly the "rest point" is calculated, and then the real time point.
1330+
// The height and angle variation are then calculated against "at rest" reference point. The air hose angle is used to rotate the hose in two directions, ie the Y and Z axis.
1331+
1332+
// Calculate height adjustment.
1333+
var rearairhoseheightadjustmentreferenceM = (float)Math.Sqrt((float)Math.Pow(CarAirHoseLengthM, 2) - (float)Math.Pow(CarAirHoseHorizontalLengthM, 2));
1334+
var frontairhoseheightadjustmentreferenceM = (float)Math.Sqrt((float)Math.Pow(CarAirHoseLengthM, 2) - (float)Math.Pow(CarBehind.CarAirHoseHorizontalLengthM, 2));
13281335

1329-
RearAirHoseHeightAdjustmentM = (float)Math.Sqrt( (float)Math.Pow(CarAirHoseLengthM, 2) - (float)Math.Pow((CouplerDistanceThisCarM + CouplerSlackM / 2.0f), 2));
1330-
CarBehind.FrontAirHoseHeightAdjustmentM = (float)Math.Sqrt((float)Math.Pow(CarAirHoseLengthM, 2) - (float)Math.Pow((CouplerDistanceBehindCarM + CouplerSlackM / 2.0f), 2));
1336+
// actual airhose height
1337+
RearAirHoseHeightAdjustmentM = (float)Math.Sqrt((float)Math.Pow(CarAirHoseLengthM, 2) - (float)Math.Pow((CarAirHoseHorizontalLengthM + CouplerSlackM), 2));
1338+
CarBehind.FrontAirHoseHeightAdjustmentM = (float)Math.Sqrt((float)Math.Pow(CarAirHoseLengthM, 2) - (float)Math.Pow((CarBehind.CarAirHoseHorizontalLengthM + CouplerSlackM), 2));
13311339

13321340
// refererence adjustment heights to rest position
1341+
// If higher then rest position, then +ve adjustment
13331342
if (RearAirHoseHeightAdjustmentM >= rearairhoseheightadjustmentreferenceM)
13341343
{
13351344
RearAirHoseHeightAdjustmentM -= rearairhoseheightadjustmentreferenceM;
13361345
}
1337-
else
1346+
else // if lower then the rest position, then -ve adjustment
13381347
{
1339-
RearAirHoseHeightAdjustmentM = rearairhoseheightadjustmentreferenceM - RearAirHoseHeightAdjustmentM;
1348+
RearAirHoseHeightAdjustmentM = (rearairhoseheightadjustmentreferenceM - RearAirHoseHeightAdjustmentM);
13401349
}
13411350

13421351
if (CarBehind.FrontAirHoseHeightAdjustmentM >= frontairhoseheightadjustmentreferenceM)
@@ -1348,31 +1357,38 @@ public void UpdateTrainDerailmentRisk()
13481357
CarBehind.FrontAirHoseHeightAdjustmentM = frontairhoseheightadjustmentreferenceM - CarBehind.FrontAirHoseHeightAdjustmentM;
13491358
}
13501359

1351-
var rearairhoseangleadjustmentreferenceRad = (float)Math.Cos(CouplerDistanceThisCarM / CarAirHoseLengthM);
1352-
var frontairhoseangleadjustmentreferenceRad = (float)Math.Cos(CouplerDistanceBehindCarM / CarAirHoseLengthM);
1360+
// Calculate angle adjustments
1361+
var rearAirhoseAngleAdjustmentReferenceRad = (float)Math.Asin(CarAirHoseHorizontalLengthM / CarAirHoseLengthM);
1362+
var frontAirhoseAngleAdjustmentReferenceRad = (float)Math.Asin(CarBehind.CarAirHoseHorizontalLengthM / CarAirHoseLengthM);
13531363

1354-
RearAirHoseAngleAdjustmentRad = (float)Math.Cos((CouplerDistanceThisCarM + CouplerSlackM / 2.0f)/ CarAirHoseLengthM);
1355-
CarBehind.FrontAirHoseAngleAdjustmentRad = (float)Math.Cos((CouplerDistanceBehindCarM + CouplerSlackM / 2.0f) / CarAirHoseLengthM);
1364+
RearAirHoseZAngleAdjustmentRad = (float)Math.Asin((CarAirHoseHorizontalLengthM + CouplerSlackM) / CarAirHoseLengthM);
1365+
CarBehind.FrontAirHoseZAngleAdjustmentRad = (float)Math.Asin((CarBehind.CarAirHoseHorizontalLengthM + CouplerSlackM) / CarAirHoseLengthM);
13561366

13571367
// refererence adjustment angles to rest position
1358-
if (RearAirHoseAngleAdjustmentRad >= rearairhoseangleadjustmentreferenceRad)
1368+
if (RearAirHoseZAngleAdjustmentRad >= rearAirhoseAngleAdjustmentReferenceRad)
13591369
{
1360-
RearAirHoseAngleAdjustmentRad -= rearairhoseangleadjustmentreferenceRad;
1370+
RearAirHoseZAngleAdjustmentRad -= rearAirhoseAngleAdjustmentReferenceRad;
13611371
}
13621372
else
13631373
{
1364-
RearAirHoseAngleAdjustmentRad = rearairhoseangleadjustmentreferenceRad - RearAirHoseAngleAdjustmentRad;
1374+
RearAirHoseZAngleAdjustmentRad = (rearAirhoseAngleAdjustmentReferenceRad - RearAirHoseZAngleAdjustmentRad);
13651375
}
13661376

1367-
if (CarBehind.FrontAirHoseAngleAdjustmentRad >= frontairhoseangleadjustmentreferenceRad)
1377+
// The Y axis angle adjustment should be the same as the z axis
1378+
RearAirHoseYAngleAdjustmentRad = RearAirHoseZAngleAdjustmentRad;
1379+
1380+
if (CarBehind.FrontAirHoseZAngleAdjustmentRad >= frontAirhoseAngleAdjustmentReferenceRad)
13681381
{
1369-
CarBehind.FrontAirHoseAngleAdjustmentRad -= frontairhoseangleadjustmentreferenceRad;
1382+
CarBehind.FrontAirHoseZAngleAdjustmentRad -= frontAirhoseAngleAdjustmentReferenceRad;
13701383
}
13711384
else
13721385
{
1373-
CarBehind.FrontAirHoseAngleAdjustmentRad = frontairhoseangleadjustmentreferenceRad - CarBehind.FrontAirHoseAngleAdjustmentRad;
1386+
CarBehind.FrontAirHoseZAngleAdjustmentRad = (frontAirhoseAngleAdjustmentReferenceRad - CarBehind.FrontAirHoseZAngleAdjustmentRad);
13741387
}
13751388

1389+
// The Y axis angle adjustment should be the same as the z axis
1390+
CarBehind.FrontAirHoseYAngleAdjustmentRad = CarBehind.FrontAirHoseZAngleAdjustmentRad;
1391+
13761392
}
13771393

13781394
// Train will derail if lateral forces on the train exceed the vertical forces holding the train on the railway track.
@@ -1385,14 +1401,13 @@ public void UpdateTrainDerailmentRisk()
13851401
if (IsPlayerTrain)
13861402
{
13871403
WagonCouplerAngleDerailRad = Math.Abs(WagonRearCouplerAngleRad);
1388-
var numWheels = WagonNumAxles * 2;
1389-
1390-
// Trace.TraceInformation("Wagon Values - CarID {0} Axles {1} Bogies {2} Wheels {3}", CarID, WagonNumAxles, WagonNumBogies, numWheels);
1404+
var numAxles = LocoNumDrvAxles + WagonNumAxles;
1405+
var numWheels = numAxles * 2;
13911406

13921407
if (CurrentCurveRadius != 0)
13931408
{
13941409
var A = MassKG * GravitationalAccelerationMpS2 / numWheels;
1395-
var B1 = (MassKG / WagonNumAxles) * (float)Math.Pow(Math.Abs(SpeedMpS), 2) / CurrentCurveRadius;
1410+
var B1 = (MassKG / numAxles) * (float)Math.Pow(Math.Abs(SpeedMpS), 2) / CurrentCurveRadius;
13961411
var B2 = GravitationalAccelerationMpS2 * (float)Math.Cos(SuperElevationAngleRad);
13971412
var B3 = CentreOfGravityM.Y / TrackGaugeM;
13981413

@@ -1404,7 +1419,7 @@ public void UpdateTrainDerailmentRisk()
14041419
if (CarAhead != null)
14051420
{
14061421
var AA1 = CarAhead.CouplerForceU * (float)Math.Sin(WagonCouplerAngleDerailRad) / WagonNumBogies;
1407-
var BB1 = MassKG / WagonNumAxles;
1422+
var BB1 = MassKG / numAxles;
14081423
var BB2 = (float)Math.Pow(Math.Abs(SpeedMpS), 2) / CurrentCurveRadius;
14091424
var BB3 = GravitationalAccelerationMpS2 * (float)Math.Sin(SuperElevationAngleRad);
14101425

Source/RunActivity/Viewer3D/RollingStock/MSTSWagonViewer.cs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,11 +1049,12 @@ private void UpdateCouplers(RenderFrame frame, ElapsedTime elapsedTime)
10491049

10501050
var quaternionCar = new Quaternion(quaternion.X, quaternion.Y, quaternion.Z, quaternion.W);
10511051

1052-
var AirHoseAngleRadians = Car.FrontAirHoseAngleAdjustmentRad;
1052+
var AirHoseYAngleRadians = Car.FrontAirHoseYAngleAdjustmentRad;
1053+
var AirHoseZAngleRadians = Car.FrontAirHoseZAngleAdjustmentRad;
10531054

10541055
AlignCouplerWithCar(Car, FrontAirHoseShape);
10551056

1056-
AdjustAirHoseAngle(Car, FrontAirHoseShape, quaternionCar, AirHoseAngleRadians);
1057+
AdjustAirHoseAngle(Car, FrontAirHoseShape, quaternionCar, AirHoseYAngleRadians, AirHoseZAngleRadians);
10571058

10581059
// Display Animation Shape
10591060
FrontAirHoseShape.PrepareFrame(frame, elapsedTime);
@@ -1113,11 +1114,12 @@ private void UpdateCouplers(RenderFrame frame, ElapsedTime elapsedTime)
11131114

11141115
var quaternionCar = new Quaternion(quaternion.X, quaternion.Y, quaternion.Z, quaternion.W);
11151116

1116-
var AirHoseAngleRadians = -Car.RearAirHoseAngleAdjustmentRad;
1117+
var AirHoseYAngleRadians = Car.RearAirHoseYAngleAdjustmentRad;
1118+
var AirHoseZAngleRadians = -Car.RearAirHoseZAngleAdjustmentRad;
11171119

11181120
AlignCouplerWithCar(Car, RearAirHoseShape);
11191121

1120-
AdjustAirHoseAngle(Car, RearAirHoseShape, quaternionCar, AirHoseAngleRadians);
1122+
AdjustAirHoseAngle(Car, RearAirHoseShape, quaternionCar, AirHoseYAngleRadians, AirHoseZAngleRadians);
11211123

11221124
// Display Animation Shape
11231125
RearAirHoseShape.PrepareFrame(frame, elapsedTime);
@@ -1230,17 +1232,17 @@ private void AdjustCouplerAngle(TrainCar adjacentCar, AnimatedShape couplerShape
12301232
/// <param name="adjacentCar"></param>
12311233
/// <param name="couplerShape"></param>
12321234
/// <param name="quaternionCar"></param>
1233-
private void AdjustAirHoseAngle(TrainCar adjacentCar, AnimatedShape airhoseShape, Quaternion quaternionCar, float angle)
1235+
private void AdjustAirHoseAngle(TrainCar adjacentCar, AnimatedShape airhoseShape, Quaternion quaternionCar, float angley, float anglez)
12341236
{
1235-
var mRotation = Matrix.CreateRotationZ(angle);
1237+
var zRotation = Matrix.CreateRotationZ(anglez);
12361238

1237-
// Rotate the coupler to align with the calculated angle direction
1238-
airhoseShape.Location.XNAMatrix = mRotation * airhoseShape.Location.XNAMatrix;
1239+
// Rotate the airhose to align with the calculated angle direction
1240+
airhoseShape.Location.XNAMatrix = zRotation * airhoseShape.Location.XNAMatrix;
12391241

1240-
// var mextRotation = Matrix.CreateRotationX(-angle);
1242+
var yRotation = Matrix.CreateRotationY(angley);
12411243

1242-
// Rotate the coupler to align with the calculated angle direction
1243-
// airhoseShape.Location.XNAMatrix = mextRotation * airhoseShape.Location.XNAMatrix;
1244+
// Rotate the airhose to align with the calculated angle direction
1245+
airhoseShape.Location.XNAMatrix = yRotation * airhoseShape.Location.XNAMatrix;
12441246

12451247
}
12461248

0 commit comments

Comments
 (0)