Skip to content

Commit e941627

Browse files
authored
Merge pull request #440 from peternewell/derail_notification#2
Addition of Derail Coefficient and further coupler animation https://blueprints.launchpad.net/or/+spec/advanced-coupler
2 parents d4a965a + e9a7e75 commit e941627

File tree

6 files changed

+568
-78
lines changed

6 files changed

+568
-78
lines changed

Source/Documentation/Manual/features-rollingstock.rst

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,45 @@ to the oscillation from center point to an oscillation end point. The file shoul
606606
one cue point at its beginning and one after the time interval of a complete bell swing
607607
forward and backward, and should have a final fadeoff for best result.
608608

609+
Coupler and Airhose Animation
610+
=============================
611+
612+
Open Rails supports animation of couplers and air hoses. Coupler animation will move the
613+
couplers and air hoses as the train moves and the coupler slack increases or decreases.
614+
Couplers will also rotate as the train travels around a curve.
615+
616+
To implement this separate models need to be provided for the couplers and air hoses. A
617+
separate model for the coupled and uncoupled state is suggested.
618+
619+
To enable coupler animation the following parameters need to be included in the coupler
620+
code section of the WAG file:
621+
622+
``FrontCouplerAnim`` - Coupler shape to be displayed at the front of the car when it is coupled.
623+
``FrontCouplerOpenAnim`` - Coupler shape to be displayed at the front of the car when it is uncoupled.
624+
``RearCouplerAnim`` - Coupler shape to be displayed at the rear of the car when it is coupled.
625+
``RearCouplerOpenAnim`` - Coupler shape to be displayed at the rear of the car when it is uncoupled
626+
627+
All four of the above will have the following format:
628+
629+
CouplerAnimation ( couplershape.s, x, y, z ) where the coupler shape file name is included along with
630+
x, y, z values that offset the coupler in the three axis.
631+
632+
For the airhose animation the following parameters must be included in the coupler code section of
633+
the WAG file:
634+
635+
``FrontAirHoseAnim`` - Air hose shape to be displayed at the front of the car when it is coupled.
636+
``FrontAirHoseDisconnectedAnim`` - Air hose shape to be displayed at the front of the car when it is uncoupled.
637+
``RearAirHoseAnim`` - Air hose shape to be displayed at the rear of the car when it is coupled.
638+
``RearAirHoseDisconnectedAnim`` - Air hose shape to be displayed at the rear of the car when it is uncoupled.
639+
640+
Each of these parameters will have the same format as indicated above for the coupler shapes.
641+
642+
Open rails uses some defaults to calculate the required movement and angles for coupler and air hose
643+
shape movement, however for greater accuracy the modeler can add specific values such as
644+
``ORTSLengthAirHose``. In addition the length values suggested in the Derailment Coefficient should
645+
also be added.
646+
647+
609648
C# engine scripting
610649
===================
611650
.. _features-scripting-csharp:

Source/Documentation/Manual/physics.rst

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,33 @@ the typical outcomes for bearing temperature heating or cooling effects.
139139
A special smoke effect, ``BearingHotboxFX``, can be added adjacent to the wagon hot box.
140140
This will be triggered if the bearing overheats.
141141

142+
Derailment Coefficient
143+
----------------------
144+
145+
The derailment coefficient indicates the likelihood that a car or wagon will derail,
146+
and is the ratio of the lateral force to vertical force acting on the wagon. This concept was
147+
first proposed by Nadal.
148+
149+
The higher the coefficient the higher the risk that a derailment will occur. Most railway
150+
companies tend to operate at a coefficient value of less then 0.8 as this gives a desireable
151+
safety margin for the car.
152+
153+
The OR calculated derailment coefficient is displayed in the Force Information HuD. The
154+
coefficient value will change colour to indicate the likelihood of the car derailing. White
155+
indicates normal operation, yellow provides a warning indication, whilst red indicates that
156+
derailment is extremely likely.
157+
158+
Open Rails uses some standard defaults that it uses to calculate the derailment coefficient,
159+
however if the modeler desires greater accuracy the following parameters can be added to the
160+
WAG/ENG file in the wagon section:
161+
162+
``ORTSLengthBogieCentre`` - length between bogie centres.
163+
``ORTSLengthCarBody`` - Length between car ends.
164+
``ORTSLengthCouplerFace`` - length between coupler faces.
165+
166+
``ORTSNumAxles`` - number of axles on the car.
167+
``ORTSNumBogies`` - number of bogies on the car.
168+
142169
.. _physics-adhesion:
143170

144171
Adhesion of Locomotives -- Settings Within the Wagon Section of ENG files

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

Lines changed: 115 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,18 @@ public virtual void LoadFromWagFile(string wagFilePath)
419419
RearCouplerShapeFileName = null;
420420
}
421421

422+
if (FrontAirHoseShapeFileName != null && !File.Exists(wagonFolderSlash + FrontAirHoseShapeFileName))
423+
{
424+
Trace.TraceWarning("{0} references non-existent shape {1}", WagFilePath, wagonFolderSlash + FrontAirHoseShapeFileName);
425+
FrontAirHoseShapeFileName = null;
426+
}
427+
428+
if (RearAirHoseShapeFileName != null && !File.Exists(wagonFolderSlash + RearAirHoseShapeFileName))
429+
{
430+
Trace.TraceWarning("{0} references non-existent shape {1}", WagFilePath, wagonFolderSlash + RearAirHoseShapeFileName);
431+
RearAirHoseShapeFileName = null;
432+
}
433+
422434
// If trailing loco resistance constant has not been defined in WAG/ENG file then assign default value based upon orig Davis values
423435
if (TrailLocoResistanceFactor == 0)
424436
{
@@ -436,6 +448,40 @@ public virtual void LoadFromWagFile(string wagFilePath)
436448
}
437449
}
438450

451+
// Initialise car body lengths. Assume overhang is 2.0m each end, and bogie centres are the car length minus this value
452+
453+
if (CarCouplerFaceLengthM == 0)
454+
{
455+
CarCouplerFaceLengthM = CarLengthM;
456+
}
457+
458+
if (CarBodyLengthM == 0)
459+
{
460+
CarBodyLengthM = CarCouplerFaceLengthM - 0.8f;
461+
}
462+
463+
if (CarBogieCentreLengthM == 0)
464+
{
465+
CarBogieCentreLengthM = (CarCouplerFaceLengthM - 4.3f);
466+
}
467+
468+
if (CarAirHoseLengthM == 0)
469+
{
470+
CarAirHoseLengthM = Me.FromIn(26.25f); // 26.25 inches
471+
}
472+
473+
var couplerlength = ((CarCouplerFaceLengthM - CarBodyLengthM) / 2) + 0.1f; // coupler length at rest, allow 0.1m also for slack
474+
475+
if (CarAirHoseLengthM < couplerlength)
476+
{
477+
CarCouplerFaceLengthM = CarBodyLengthM + (0.4f * 2.0f); // Assume a coupler length of 400mm at each end and add to car body length
478+
479+
if (Simulator.Settings.VerboseConfigurationMessages)
480+
{
481+
Trace.TraceInformation("Coupler length exceeded brake air hose length, so ORTSLengthCouplerFace decreased to {0}", CarCouplerFaceLengthM);
482+
}
483+
}
484+
439485
// Ensure Drive Axles is set to a default if no OR value added to WAG file
440486
if (WagonNumAxles == 0)
441487
{
@@ -964,6 +1010,10 @@ public virtual void Parse(string lowercasetoken, STFReader stf)
9641010
CarLengthM = stf.ReadFloat(STFReader.UNITS.Distance, null);
9651011
stf.SkipRestOfBlock();
9661012
break;
1013+
case "wagon(ortslengthbogiecentre": CarBogieCentreLengthM = stf.ReadFloatBlock(STFReader.UNITS.Distance, null); break;
1014+
case "wagon(ortslengthcarbody": CarBodyLengthM = stf.ReadFloatBlock(STFReader.UNITS.Distance, null); break;
1015+
case "wagon(ortslengthairhose": CarAirHoseLengthM = stf.ReadFloatBlock(STFReader.UNITS.Distance, null); break;
1016+
case "wagon(ortslengthcouplerface": CarCouplerFaceLengthM = stf.ReadFloatBlock(STFReader.UNITS.Distance, null); break;
9671017
case "wagon(ortstrackgauge":
9681018
stf.MustMatch("(");
9691019
TrackGaugeM = stf.ReadFloat(STFReader.UNITS.Distance, null);
@@ -1121,6 +1171,15 @@ public virtual void Parse(string lowercasetoken, STFReader stf)
11211171
stf.SkipRestOfBlock();
11221172
break;
11231173

1174+
case "wagon(coupling(frontairhoseanim":
1175+
stf.MustMatch("(");
1176+
FrontAirHoseShapeFileName = stf.ReadString();
1177+
FrontAirHoseAnimWidthM = stf.ReadFloat(STFReader.UNITS.Distance, null);
1178+
FrontAirHoseAnimHeightM = stf.ReadFloat(STFReader.UNITS.Distance, null);
1179+
FrontAirHoseAnimLengthM = stf.ReadFloat(STFReader.UNITS.Distance, null);
1180+
stf.SkipRestOfBlock();
1181+
break;
1182+
11241183
case "wagon(coupling(rearcoupleranim":
11251184
stf.MustMatch("(");
11261185
RearCouplerShapeFileName = stf.ReadString();
@@ -1130,7 +1189,16 @@ public virtual void Parse(string lowercasetoken, STFReader stf)
11301189
stf.SkipRestOfBlock();
11311190
break;
11321191

1133-
case "wagon(coupling(spring(ortstensionstiffness":
1192+
case "wagon(coupling(rearairhoseanim":
1193+
stf.MustMatch("(");
1194+
RearAirHoseShapeFileName = stf.ReadString();
1195+
RearAirHoseAnimWidthM = stf.ReadFloat(STFReader.UNITS.Distance, null);
1196+
RearAirHoseAnimHeightM = stf.ReadFloat(STFReader.UNITS.Distance, null);
1197+
RearAirHoseAnimLengthM = stf.ReadFloat(STFReader.UNITS.Distance, null);
1198+
stf.SkipRestOfBlock();
1199+
break;
1200+
1201+
case "wagon(coupling(spring(ortstensionstiffness":
11341202
stf.MustMatch("(");
11351203
Couplers[CouplerCountLocation].SetTensionStiffness(stf.ReadFloat(STFReader.UNITS.Force, null), stf.ReadFloat(STFReader.UNITS.Force, null));
11361204
stf.SkipRestOfBlock();
@@ -1156,6 +1224,25 @@ public virtual void Parse(string lowercasetoken, STFReader stf)
11561224
stf.SkipRestOfBlock();
11571225
break;
11581226

1227+
case "wagon(coupling(frontairhosediconnectedanim":
1228+
stf.MustMatch("(");
1229+
FrontAirHoseDisconnectedShapeFileName = stf.ReadString();
1230+
FrontAirHoseDisconnectedAnimWidthM = stf.ReadFloat(STFReader.UNITS.Distance, null);
1231+
FrontAirHoseDisconnectedAnimHeightM = stf.ReadFloat(STFReader.UNITS.Distance, null);
1232+
FrontAirHoseDisconnectedAnimLengthM = stf.ReadFloat(STFReader.UNITS.Distance, null);
1233+
stf.SkipRestOfBlock();
1234+
break;
1235+
1236+
case "wagon(coupling(rearairhosediconnectedanim":
1237+
stf.MustMatch("(");
1238+
RearAirHoseDisconnectedShapeFileName = stf.ReadString();
1239+
RearAirHoseDisconnectedAnimWidthM = stf.ReadFloat(STFReader.UNITS.Distance, null);
1240+
RearAirHoseDisconnectedAnimHeightM = stf.ReadFloat(STFReader.UNITS.Distance, null);
1241+
RearAirHoseDisconnectedAnimLengthM = stf.ReadFloat(STFReader.UNITS.Distance, null);
1242+
stf.SkipRestOfBlock();
1243+
break;
1244+
1245+
11591246
case "wagon(coupling(spring(ortscompressionstiffness":
11601247
stf.MustMatch("(");
11611248
Couplers[CouplerCountLocation].SetCompressionStiffness(stf.ReadFloat(STFReader.UNITS.Force, null), stf.ReadFloat(STFReader.UNITS.Force, null));
@@ -1247,7 +1334,7 @@ public virtual void Parse(string lowercasetoken, STFReader stf)
12471334
case "wagon(orts3dcab": Parse3DCab(stf); break;
12481335
case "wagon(numwheels": MSTSWagonNumWheels= stf.ReadFloatBlock(STFReader.UNITS.None, 4.0f); break;
12491336
case "wagon(ortsnumberaxles": WagonNumAxles = stf.ReadIntBlock(null); break;
1250-
1337+
case "wagon(ortsnumberbogies": WagonNumBogies = stf.ReadIntBlock(null); break;
12511338
case "wagon(ortspantographs":
12521339
Pantographs.Parse(lowercasetoken, stf);
12531340
break;
@@ -1322,6 +1409,27 @@ public virtual void Copy(MSTSWagon copy)
13221409
RearCouplerOpenAnimHeightM = copy.RearCouplerOpenAnimHeightM;
13231410
RearCouplerOpenAnimLengthM = copy.RearCouplerOpenAnimLengthM;
13241411
RearCouplerOpenFitted = copy.RearCouplerOpenFitted;
1412+
1413+
FrontAirHoseShapeFileName = copy.FrontAirHoseShapeFileName;
1414+
FrontAirHoseAnimWidthM = copy.FrontAirHoseAnimWidthM;
1415+
FrontAirHoseAnimHeightM = copy.FrontAirHoseAnimHeightM;
1416+
FrontAirHoseAnimLengthM = copy.FrontAirHoseAnimLengthM;
1417+
1418+
FrontAirHoseDisconnectedShapeFileName = copy.FrontAirHoseDisconnectedShapeFileName;
1419+
FrontAirHoseDisconnectedAnimWidthM = copy.FrontAirHoseDisconnectedAnimWidthM;
1420+
FrontAirHoseDisconnectedAnimHeightM = copy.FrontAirHoseDisconnectedAnimHeightM;
1421+
FrontAirHoseDisconnectedAnimLengthM = copy.FrontAirHoseDisconnectedAnimLengthM;
1422+
1423+
RearAirHoseShapeFileName = copy.RearAirHoseShapeFileName;
1424+
RearAirHoseAnimWidthM = copy.RearAirHoseAnimWidthM;
1425+
RearAirHoseAnimHeightM = copy.RearAirHoseAnimHeightM;
1426+
RearAirHoseAnimLengthM = copy.RearAirHoseAnimLengthM;
1427+
1428+
RearAirHoseDisconnectedShapeFileName = copy.RearAirHoseDisconnectedShapeFileName;
1429+
RearAirHoseDisconnectedAnimWidthM = copy.RearAirHoseDisconnectedAnimWidthM;
1430+
RearAirHoseDisconnectedAnimHeightM = copy.RearAirHoseDisconnectedAnimHeightM;
1431+
RearAirHoseDisconnectedAnimLengthM = copy.RearAirHoseDisconnectedAnimLengthM;
1432+
13251433
CarWidthM = copy.CarWidthM;
13261434
CarHeightM = copy.CarHeightM;
13271435
CarLengthM = copy.CarLengthM;
@@ -1330,10 +1438,15 @@ public virtual void Copy(MSTSWagon copy)
13301438
InitialCentreOfGravityM = copy.InitialCentreOfGravityM;
13311439
UnbalancedSuperElevationM = copy.UnbalancedSuperElevationM;
13321440
RigidWheelBaseM = copy.RigidWheelBaseM;
1441+
CarBogieCentreLengthM = copy.CarBogieCentreLengthM;
1442+
CarBodyLengthM = copy.CarBodyLengthM;
1443+
CarCouplerFaceLengthM = copy.CarCouplerFaceLengthM;
1444+
CarAirHoseLengthM = copy.CarAirHoseLengthM;
13331445
AuxTenderWaterMassKG = copy.AuxTenderWaterMassKG;
13341446
TenderWagonMaxCoalMassKG = copy.TenderWagonMaxCoalMassKG;
13351447
TenderWagonMaxWaterMassKG = copy.TenderWagonMaxWaterMassKG;
13361448
WagonNumAxles = copy.WagonNumAxles;
1449+
WagonNumBogies = copy.WagonNumBogies;
13371450
MSTSWagonNumWheels = copy.MSTSWagonNumWheels;
13381451
MassKG = copy.MassKG;
13391452
InitialMassKG = copy.InitialMassKG;

0 commit comments

Comments
 (0)