Skip to content

Commit e5d8f1c

Browse files
authored
Merge pull request #559 from Csantucci/Distributed-power-cab-display
https://blueprints.launchpad.net/or/+spec/distributed-power: Distributed power cab display and controls
2 parents f1451af + c7f1150 commit e5d8f1c

File tree

9 files changed

+771
-10
lines changed

9 files changed

+771
-10
lines changed

Source/Documentation/Manual/cabs.rst

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,67 @@ Here is an example of use of the odometer control blocks within a .cvf file::
403403
Units ( FEET )
404404
)
405405

406+
.. _cabs-distributed-power:
407+
408+
Distributed Power
409+
-----------------
410+
411+
The principles of Distributed Power are described :ref:`here <distributed-power>` .
412+
413+
Distributed Power data can be displayed using control ORTS_DISTRIBUTED_POWER. Here
414+
an example of use::
415+
416+
ScreenDisplay (
417+
Type ( ORTS_DISTRIBUTED_POWER SCREEN_DISPLAY )
418+
Position ( 164.4 286.5 136 52 )
419+
Parameters (
420+
FullTable True
421+
LoadUnits AMPS
422+
)
423+
Units ( KM_PER_HOUR )
424+
ORTSDisplay ( 1 )
425+
ORTSScreenPage ( "2300-0" )
426+
)
427+
428+
Here below an example of the output of the above control.
429+
430+
.. image:: images/cabs-distributed-power.png
431+
432+
When parameter FullTable is set to False, only the first 6 lines
433+
are displayed.
434+
Optional parameter LoadUnits defines which is the UoM used for the
435+
Load field. Default is AMPS in a metric environment and KILO_LBS in
436+
the other cases. Selectable LoadUnits are AMPS, NEWTONS, KILO_NEWTONS,
437+
LBS and KILO_KBS.
438+
439+
The screen display can be rotated adding parameter
440+
ORTSAngle ( number ) in the ScreenDisplay block. The angle is in degrees.
441+
442+
For every keyboard command related to Distributed Power, a cabview control
443+
is also available. Here's a list of the cabview controls::
444+
445+
- ORTS_DP_MOVE_TO_FRONT
446+
- ORTS_DP_MOVE_TO_BACK
447+
- ORTS_DP_IDLE
448+
- ORTS_DP_TRACTION
449+
- ORTS_DP_BRAKE
450+
- ORTS_DP_MORE
451+
- ORTS_DP_LESS
452+
453+
Here an example of use of one of the controls::
454+
455+
TwoState (
456+
Type ( ORTS_DP_MOVE_TO_FRONT TWO_STATE )
457+
Position ( 163.2 378.4 13.75 10 )
458+
Graphic ( "..\\..\\Common.Cab\\ES44v3\\softkey1trans.ace" )
459+
NumFrames ( 2 2 1 )
460+
Style ( WHILE_PRESSED )
461+
MouseControl ( 1 )
462+
ORTSDisplay ( 1 )
463+
ORTSScreenPage ( "2300-0" )
464+
)
465+
466+
406467
Animated 2D Wipers
407468
------------------
408469

Loading
Loading

Source/Documentation/Manual/physics.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2040,6 +2040,8 @@ unit) signals for braking and throttle position, etc. The
20402040
player-controlled locomotive generates the MU signals which are passed
20412041
along to every unit in the train.
20422042

2043+
.. _distributed-power:
2044+
20432045
Distributed Power
20442046
-----------------
20452047

@@ -2114,6 +2116,9 @@ The actual set value of traction or dynamic brake of *async* group is shown in
21142116
lines *Throttle* and *Dynamic Brake*, respectively, in brackets, e.g.:
21152117
Throttle: 0% (50%).
21162118

2119+
Distributed power info and commands can also be displayed and operated through
2120+
cabview controls, as explained :ref:`here <cabs-distributed-power>`
2121+
21172122
The complete distributed power configuration is displayed in the
21182123
Distributed Power Info extended HUD page, where the state of all locomotives
21192124
in the train are shown, as well as in the *Train DPU Info* window, which is

Source/Orts.Formats.Msts/CabViewFile.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,9 +257,18 @@ public enum CABViewControlTypes
257257
ORTS_TCS47,
258258
ORTS_TCS48,
259259
ORTS_ETCS,
260+
260261
ORTS_ODOMETER,
261262
ORTS_ODOMETER_RESET,
262263
ORTS_ODOMETER_DIRECTION,
264+
ORTS_DISTRIBUTED_POWER,
265+
ORTS_DP_MOVE_TO_FRONT,
266+
ORTS_DP_MOVE_TO_BACK,
267+
ORTS_DP_IDLE,
268+
ORTS_DP_TRACTION,
269+
ORTS_DP_BRAKE,
270+
ORTS_DP_MORE,
271+
ORTS_DP_LESS,
263272

264273
// Further CabViewControlTypes must be added above this line, to avoid their malfunction in 3DCabs
265274
EXTERNALWIPERS,

Source/Orts.Simulation/Simulation/RollingStocks/MSTSDieselLocomotive.cs

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -918,7 +918,6 @@ public string GetDPDebugStatus()
918918
throttle += "???";
919919

920920
var status = new StringBuilder();
921-
922921
status.AppendFormat("{0}({1})\t", CarID, DPUnitID);
923922
status.AppendFormat("{0} {1}\t", GetStringAttribute.GetPrettyName(Direction), Flipped ? Simulator.Catalog.GetString("(flipped)") : "");
924923
status.AppendFormat("{0}\t", IsLeadLocomotive() || RemoteControlGroup < 0 ? "———" : RemoteControlGroup == 0 ? Simulator.Catalog.GetString("Sync") : Simulator.Catalog.GetString("Async"));
@@ -930,7 +929,7 @@ public string GetDPDebugStatus()
930929
return status.ToString();
931930
}
932931

933-
public string GetDpuStatus(bool dataDpu)// used by the TrainDpuInfo window
932+
public string GetDpuStatus(bool dataDpu, CABViewControlUnits loadUnits = CABViewControlUnits.NONE)// used by the TrainDpuInfo window
934933
{
935934
string throttle = "";
936935
if (ThrottlePercent > 0)
@@ -967,16 +966,63 @@ public string GetDpuStatus(bool dataDpu)// used by the TrainDpuInfo window
967966
status.AppendFormat("{0}({1})\t", CarID, DPUnitID);
968967
// Throttle
969968
status.AppendFormat("{0}\t", throttle);
969+
970970
// Load
971-
foreach (var eng in DieselEngines.DEList)
972-
status.AppendFormat("{0:F1}%\t", eng.LoadPercent);
971+
var data = 0f;
972+
if (FilteredMotiveForceN != 0)
973+
data = Math.Abs(this.FilteredMotiveForceN);
974+
else
975+
data = Math.Abs(this.LocomotiveAxle.DriveForceN);
976+
if (DynamicBrakePercent > 0)
977+
{
978+
data = -Math.Abs(DynamicBrakeForceN);
979+
}
980+
if (loadUnits == CABViewControlUnits.NONE)
981+
loadUnits = IsMetric ? CABViewControlUnits.AMPS : CABViewControlUnits.KILO_LBS;
982+
switch (loadUnits)
983+
{
984+
case CABViewControlUnits.AMPS:
985+
if (ThrottlePercent > 0)
986+
{
987+
data = (data / MaxForceN) * MaxCurrentA;
988+
}
989+
if (DynamicBrakePercent > 0)
990+
{
991+
data = (data / MaxDynamicBrakeForceN) * DynamicBrakeMaxCurrentA;
992+
}
993+
status.AppendFormat("{0:F0} A", data);
994+
break;
995+
996+
case CABViewControlUnits.NEWTONS:
997+
status.AppendFormat("{0:F0} N", data);
998+
break;
999+
1000+
case CABViewControlUnits.KILO_NEWTONS:
1001+
data = data / 1000.0f;
1002+
status.AppendFormat("{0:F0} kN", data);
1003+
break;
1004+
1005+
case CABViewControlUnits.LBS:
1006+
data = N.ToLbf(data);
1007+
status.AppendFormat("{0:F0} l", data);
1008+
break;
1009+
1010+
case CABViewControlUnits.KILO_LBS:
1011+
default:
1012+
data = N.ToLbf(data) * 0.001f;
1013+
status.AppendFormat("{0:F0} K", data);
1014+
break;
1015+
}
1016+
1017+
status.AppendFormat((data < 0 ? "???" : " ") + "\t");
1018+
9731019
// BP
9741020
var brakeInfoValue = brakeValue(Simulator.Catalog.GetString("BP"), Simulator.Catalog.GetString("EOT"));
9751021
status.AppendFormat("{0:F0}\t", brakeInfoValue);
9761022

977-
// Flow
978-
foreach (var eng in DieselEngines.DEList)
979-
status.AppendFormat("{0}/{1}\t", FormatStrings.FormatFuelVolume(pS.TopH(eng.DieselFlowLps), Simulator.PlayerLocomotive.IsMetric, Simulator.PlayerLocomotive.IsUK), FormatStrings.h);
1023+
// Flow.
1024+
// TODO:The BP air flow that feeds the brake tube is not yet modeled in Open Rails.
1025+
9801026
// Remote
9811027
if (dataDpu)
9821028
{
@@ -993,7 +1039,7 @@ public string GetDpuStatus(bool dataDpu)// used by the TrainDpuInfo window
9931039
status.AppendFormat("{0:F0}\t", brakeInfoValue);
9941040

9951041
// BC
996-
brakeInfoValue = brakeValue(Simulator.Catalog.GetString("BC"), Simulator.Catalog.GetString("BP"));
1042+
brakeInfoValue = Math.Round(BrakeSystem.GetCylPressurePSI()).ToString() + " psi";
9971043
status.AppendFormat("{0:F0}\t", brakeInfoValue);
9981044

9991045
// MR
@@ -1073,13 +1119,11 @@ private static void SetDPULabels(bool dpuFull, int numberOfEngines)
10731119
labels.AppendFormat("{0}\t", Simulator.Catalog.GetString("Throttle"));
10741120
labels.AppendFormat("{0}\t", Simulator.Catalog.GetString("Load"));
10751121
labels.AppendFormat("{0}\t", Simulator.Catalog.GetString("BP"));
1076-
labels.AppendFormat("{0}\t", Simulator.Catalog.GetString("Flow"));
10771122
if (!dpuFull)
10781123
{
10791124
labels.AppendFormat("{0}", Simulator.Catalog.GetString("Remote"));
10801125
DpuLabels = labels.ToString().Split('\t');
10811126
}
1082-
10831127
if (dpuFull)
10841128
{
10851129
labels.AppendFormat("{0}\t", Simulator.Catalog.GetString("Remote"));

Source/RunActivity/RunActivity.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@
171171
<Compile Include="Viewer3D\RollingStock\MSTSLocomotiveViewer.cs" />
172172
<Compile Include="Viewer3D\RollingStock\MSTSSteamLocomotiveViewer.cs" />
173173
<Compile Include="Viewer3D\RollingStock\MSTSWagonViewer.cs" />
174+
<Compile Include="Viewer3D\RollingStock\SubSystems\DistributedPowerInterface.cs" />
174175
<Compile Include="Viewer3D\RollingStock\SubSystems\ETCS\DataEntry.cs" />
175176
<Compile Include="Viewer3D\RollingStock\SubSystems\ETCS\Menus.cs" />
176177
<Compile Include="Viewer3D\RollingStock\SubSystems\ETCS\TextMessages.cs" />

Source/RunActivity/Viewer3D/RollingStock/MSTSLocomotiveViewer.cs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
using Orts.Simulation.RollingStocks.SubSystems.Controllers;
3333
using Orts.Viewer3D.Common;
3434
using Orts.Viewer3D.Popups;
35+
using Orts.Viewer3D.RollingStock.SubSystems;
3536
using Orts.Viewer3D.RollingStock.Subsystems.ETCS;
3637
using ORTS.Common;
3738
using ORTS.Common.Input;
@@ -1211,6 +1212,15 @@ public CabRenderer(Viewer viewer, MSTSLocomotive car)
12111212
count[(int)cvc.ControlType]++;
12121213
continue;
12131214
}
1215+
else if (screen.ControlType == CABViewControlTypes.ORTS_DISTRIBUTED_POWER)
1216+
{
1217+
var cvr = new DistributedPowerInterfaceRenderer(viewer, car, screen, _Shader);
1218+
cvr.SortIndex = controlSortIndex;
1219+
CabViewControlRenderersList[i].Add(cvr);
1220+
if (!ControlMap.ContainsKey(key)) ControlMap.Add(key, cvr);
1221+
count[(int)cvc.ControlType]++;
1222+
continue;
1223+
}
12141224
}
12151225
}
12161226
}
@@ -1323,6 +1333,15 @@ public CabRenderer(Viewer viewer, MSTSLocomotive car, CabViewFile CVFFile) //use
13231333
count[(int)cvc.ControlType]++;
13241334
continue;
13251335
}
1336+
else if (screen.ControlType == CABViewControlTypes.ORTS_DISTRIBUTED_POWER)
1337+
{
1338+
var cvr = new DistributedPowerInterfaceRenderer(viewer, car, screen, _Shader);
1339+
cvr.SortIndex = controlSortIndex;
1340+
CabViewControlRenderersList[i].Add(cvr);
1341+
if (!ControlMap.ContainsKey(key)) ControlMap.Add(key, cvr);
1342+
count[(int)cvc.ControlType]++;
1343+
continue;
1344+
}
13261345
}
13271346
}
13281347
#endregion
@@ -2100,6 +2119,13 @@ public int GetDrawIndex()
21002119
index = (int)data;
21012120
break;
21022121
case CABViewControlTypes.ORTS_SCREEN_SELECT:
2122+
case CABViewControlTypes.ORTS_DP_MOVE_TO_BACK:
2123+
case CABViewControlTypes.ORTS_DP_MOVE_TO_FRONT:
2124+
case CABViewControlTypes.ORTS_DP_TRACTION:
2125+
case CABViewControlTypes.ORTS_DP_IDLE:
2126+
case CABViewControlTypes.ORTS_DP_BRAKE:
2127+
case CABViewControlTypes.ORTS_DP_MORE:
2128+
case CABViewControlTypes.ORTS_DP_LESS:
21032129
index = ButtonState ? 1 : 0;
21042130
break;
21052131
case CABViewControlTypes.ORTS_STATIC_DISPLAY:
@@ -2420,6 +2446,49 @@ public void HandleUserInput()
24202446
new TCSButtonCommand(Viewer.Log, !Locomotive.TrainControlSystem.TCSCommandButtonDown[commandIndex], commandIndex);
24212447
new TCSSwitchCommand(Viewer.Log, ChangedValue(Locomotive.TrainControlSystem.TCSCommandSwitchOn[commandIndex] ? 1 : 0) > 0, commandIndex);
24222448
break;
2449+
2450+
case CABViewControlTypes.ORTS_DP_MOVE_TO_FRONT:
2451+
buttonState = ChangedValue(ButtonState ? 1 : 0) > 0;
2452+
if (!ButtonState && (ButtonState ? 1 : 0) != ChangedValue(ButtonState ? 1 : 0))
2453+
new DPMoveToFrontCommand(Viewer.Log);
2454+
ButtonState = buttonState;
2455+
break;
2456+
case CABViewControlTypes.ORTS_DP_MOVE_TO_BACK:
2457+
buttonState = ChangedValue(ButtonState ? 1 : 0) > 0;
2458+
if (!ButtonState && (ButtonState ? 1 : 0) != ChangedValue(ButtonState ? 1 : 0))
2459+
new DPMoveToBackCommand(Viewer.Log);
2460+
ButtonState = buttonState;
2461+
break;
2462+
case CABViewControlTypes.ORTS_DP_IDLE:
2463+
buttonState = ChangedValue(ButtonState ? 1 : 0) > 0;
2464+
if (!ButtonState && (ButtonState ? 1 : 0) != ChangedValue(ButtonState ? 1 : 0))
2465+
new DPIdleCommand(Viewer.Log);
2466+
ButtonState = buttonState;
2467+
break;
2468+
case CABViewControlTypes.ORTS_DP_TRACTION:
2469+
buttonState = ChangedValue(ButtonState ? 1 : 0) > 0;
2470+
if (!ButtonState && (ButtonState ? 1 : 0) != ChangedValue(ButtonState ? 1 : 0))
2471+
new DPTractionCommand(Viewer.Log);
2472+
ButtonState = buttonState;
2473+
break;
2474+
case CABViewControlTypes.ORTS_DP_BRAKE:
2475+
buttonState = ChangedValue(ButtonState ? 1 : 0) > 0;
2476+
if (!ButtonState && (ButtonState ? 1 : 0) != ChangedValue(ButtonState ? 1 : 0))
2477+
new DPDynamicBrakeCommand(Viewer.Log);
2478+
ButtonState = buttonState;
2479+
break;
2480+
case CABViewControlTypes.ORTS_DP_MORE:
2481+
buttonState = ChangedValue(ButtonState ? 1 : 0) > 0;
2482+
if (!ButtonState && (ButtonState ? 1 : 0) != ChangedValue(ButtonState ? 1 : 0))
2483+
new DPMoreCommand(Viewer.Log);
2484+
ButtonState = buttonState;
2485+
break;
2486+
case CABViewControlTypes.ORTS_DP_LESS:
2487+
buttonState = ChangedValue(ButtonState ? 1 : 0) > 0;
2488+
if (!ButtonState && (ButtonState ? 1 : 0) != ChangedValue(ButtonState ? 1 : 0))
2489+
new DPLessCommand(Viewer.Log);
2490+
ButtonState = buttonState;
2491+
break;
24232492
}
24242493

24252494
}

0 commit comments

Comments
 (0)