Skip to content

Commit 959de23

Browse files
authored
Merge pull request #1000 from cesarBLG/control-car-controls
Locomotive operation from control car
2 parents da57f73 + d8d9709 commit 959de23

File tree

12 files changed

+419
-210
lines changed

12 files changed

+419
-210
lines changed

Source/Documentation/Manual/physics.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -2419,7 +2419,7 @@ To allow the auxiliary tender to be filled at a water fuelling point, a water fr
24192419
Unpowered Control Car
24202420
---------------------
24212421

2422-
This module simulates the control cab of a DMU set of cars. The cab typically would be located in an unpowered
2422+
This module simulates the control cab of a MU set of cars. The cab typically would be located in an unpowered
24232423
trailer car which is attached to a powered car for the provision of its motive force to drive the train forward.
24242424

24252425
Apart from producing motive force the car (and cabin controls) should behave exactly the same as a locomotive.

Source/Orts.Simulation/Common/Commands.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2155,7 +2155,7 @@ public override void Redo()
21552155
[Serializable()]
21562156
public sealed class TogglePlayerEngineCommand : Command
21572157
{
2158-
public static MSTSDieselLocomotive Receiver { get; set; }
2158+
public static MSTSLocomotive Receiver { get; set; }
21592159

21602160
public TogglePlayerEngineCommand(CommandLog log)
21612161
: base(log)

Source/Orts.Simulation/Common/Scripting/PowerSupply/ControlCarPowerSupply.cs

+33-7
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
// along with Open Rails. If not, see <http://www.gnu.org/licenses/>.
1717

1818
using System;
19+
using Orts.Simulation.RollingStocks;
1920

2021
namespace ORTS.Scripting.Api
2122
{
@@ -24,12 +25,37 @@ namespace ORTS.Scripting.Api
2425
/// </summary>
2526
public abstract class ControlCarPowerSupply : LocomotivePowerSupply
2627
{
27-
28-
29-
30-
31-
32-
28+
MSTSLocomotive ControlActiveLocomotive => Locomotive.ControlActiveLocomotive;
29+
/// <summary>
30+
/// Index of the control active locomotive in the train (taking into account only locomotives)
31+
/// </summary>
32+
public int IndexOfControlActiveLocomotive
33+
{
34+
get
35+
{
36+
int count=0;
37+
for (int i=0; i<Train.Cars.Count; i++)
38+
{
39+
if (Train.Cars[i] is MSTSLocomotive)
40+
{
41+
if (Train.Cars[i] == ControlActiveLocomotive) return count;
42+
count++;
43+
}
44+
}
45+
return -1;
46+
}
47+
}
48+
protected override void SetCurrentMainPowerSupplyState(PowerSupplyState state) {}
49+
protected override void SetCurrentAuxiliaryPowerSupplyState(PowerSupplyState state) {}
50+
protected override void SetCurrentElectricTrainSupplyState(PowerSupplyState state) {}
51+
protected override void SetCurrentDynamicBrakeAvailability(bool avail) {}
52+
public void SignalEventToControlActiveLocomotive(PowerSupplyEvent evt)
53+
{
54+
ControlActiveLocomotive.LocomotivePowerSupply.HandleEvent(evt);
55+
}
56+
public void SignalEventToControlActiveLocomotive(PowerSupplyEvent evt, int id)
57+
{
58+
ControlActiveLocomotive.LocomotivePowerSupply.HandleEvent(evt, id);
59+
}
3360
}
34-
3561
}

Source/Orts.Simulation/Common/Scripting/PowerSupply/LocomotivePowerSupply.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -270,13 +270,13 @@ protected void SetCustomizedCabviewControlName(int index, string name)
270270
/// Sets the current state of the main power supply (power from the pantograph or the generator)
271271
/// Main power comes from the pantograph or the diesel generator
272272
/// </summary>
273-
protected void SetCurrentMainPowerSupplyState(PowerSupplyState state) => LpsHost.MainPowerSupplyState = state;
273+
protected virtual void SetCurrentMainPowerSupplyState(PowerSupplyState state) => LpsHost.MainPowerSupplyState = state;
274274

275275
/// <summary>
276276
/// Sets the current state of the auxiliary power supply
277277
/// Auxiliary power is used by auxiliary systems of a locomotive (such as ventilation or air compressor) and by systems of the cars (such as air conditionning)
278278
/// </summary>
279-
protected void SetCurrentAuxiliaryPowerSupplyState(PowerSupplyState state) => LpsHost.AuxiliaryPowerSupplyState = state;
279+
protected virtual void SetCurrentAuxiliaryPowerSupplyState(PowerSupplyState state) => LpsHost.AuxiliaryPowerSupplyState = state;
280280

281281
/// <summary>
282282
/// Sets the current state of the cab power supply
@@ -287,11 +287,11 @@ protected void SetCustomizedCabviewControlName(int index, string name)
287287
/// Sets the current state of the electric train supply
288288
/// ETS is used by the systems of the cars (such as air conditionning)
289289
/// </summary>
290-
protected void SetCurrentElectricTrainSupplyState(PowerSupplyState state) => LpsHost.ElectricTrainSupplyState = state;
290+
protected virtual void SetCurrentElectricTrainSupplyState(PowerSupplyState state) => LpsHost.ElectricTrainSupplyState = state;
291291
/// <summary>
292292
/// Sets the current availability of the dynamic brake
293293
/// </summary>
294-
protected void SetCurrentDynamicBrakeAvailability(bool avail) => LpsHost.DynamicBrakeAvailable = avail;
294+
protected virtual void SetCurrentDynamicBrakeAvailability(bool avail) => LpsHost.DynamicBrakeAvailable = avail;
295295

296296
/// <summary>
297297
/// Sends an event to the master switch

Source/Orts.Simulation/Simulation/RollingStocks/MSTSControlTrailerCar.cs

+133-30
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// COPYRIGHT 2009, 2010, 2011, 2012, 2013 by the Open Rails project.
1+
// COPYRIGHT 2009 by the Open Rails project.
22
//
33
// This file is part of Open Rails.
44
//
@@ -15,27 +15,16 @@
1515
// You should have received a copy of the GNU General Public License
1616
// along with Open Rails. If not, see <http://www.gnu.org/licenses/>.
1717

18-
/* DIESEL LOCOMOTIVE CLASSES
19-
*
20-
* The Locomotive is represented by two classes:
21-
* MSTSDieselLocomotiveSimulator - defines the behaviour, ie physics, motion, power generated etc
22-
* MSTSDieselLocomotiveViewer - defines the appearance in a 3D viewer. The viewer doesn't
23-
* get attached to the car until it comes into viewing range.
24-
*
25-
* Both these classes derive from corresponding classes for a basic locomotive
26-
* LocomotiveSimulator - provides for movement, basic controls etc
27-
* LocomotiveViewer - provides basic animation for running gear, wipers, etc
28-
*
29-
*/
30-
3118
using System.Diagnostics;
3219
using System.IO;
3320
using System.Text;
21+
using Orts.Formats.Msts;
3422
using Orts.Parsers.Msts;
3523
using Orts.Simulation.Physics;
3624
using Orts.Simulation.RollingStocks.SubSystems.Controllers;
3725
using Orts.Simulation.RollingStocks.SubSystems.PowerSupplies;
3826
using Orts.Simulation.RollingStocks.SubSystems.PowerTransmissions;
27+
using ORTS.Common;
3928

4029
namespace Orts.Simulation.RollingStocks
4130
{
@@ -49,17 +38,14 @@ public class MSTSControlTrailerCar : MSTSLocomotive
4938
int ControlGearIndication;
5039
TypesGearBox ControlGearBoxType;
5140

41+
private bool controlTrailerBrakeSystemSet = false;
42+
5243
public MSTSControlTrailerCar(Simulator simulator, string wagFile)
5344
: base(simulator, wagFile)
5445
{
5546
PowerSupply = new ScriptedControlCarPowerSupply(this);
5647
}
5748

58-
public override void LoadFromWagFile(string wagFilePath)
59-
{
60-
base.LoadFromWagFile(wagFilePath);
61-
}
62-
6349
public override void Initialize()
6450
{
6551
// Initialise gearbox controller
@@ -83,18 +69,12 @@ public override void Parse(string lowercasetoken, STFReader stf)
8369
{
8470
switch (lowercasetoken)
8571
{
86-
case "engine(ortspowerondelay":
87-
case "engine(ortsauxpowerondelay":
8872
case "engine(ortspowersupply":
8973
case "engine(ortspowersupplyparameters":
90-
case "engine(ortstractioncutoffrelay":
91-
case "engine(ortstractioncutoffrelayclosingdelay":
9274
case "engine(ortsbattery":
9375
case "engine(ortsmasterkey(mode":
9476
case "engine(ortsmasterkey(delayoff":
9577
case "engine(ortsmasterkey(headlightcontrol":
96-
case "engine(ortselectrictrainsupply(mode":
97-
case "engine(ortselectrictrainsupply(dieselengineminrpm":
9878
LocomotivePowerSupply.Parse(lowercasetoken, stf);
9979
break;
10080

@@ -161,6 +141,31 @@ public override void InitializeMoving()
161141
/// </summary>
162142
public override void Update(float elapsedClockSeconds)
163143
{
144+
FindControlActiveLocomotive();
145+
// A control car typically doesn't have its own compressor and relies on the attached power car. However OR uses the lead locomotive as the reference car for compressor calculations.
146+
// Hence whilst users are encouraged to leave these parameters out of the ENG file, they need to be setup for OR to work correctly.
147+
// Some parameters need to be split across the unpowered and powered car for correct timing and volume calculations.
148+
// This setup loop is only processed the first time that update is run.
149+
if (!controlTrailerBrakeSystemSet)
150+
{
151+
if (ControlActiveLocomotive != null)
152+
{
153+
// Split reservoir volume across the power car and the active locomotive
154+
MainResVolumeM3 = ControlActiveLocomotive.MainResVolumeM3 / 2;
155+
ControlActiveLocomotive.MainResVolumeM3 = MainResVolumeM3;
156+
157+
MaxMainResPressurePSI = ControlActiveLocomotive.MaxMainResPressurePSI;
158+
MainResPressurePSI = MaxMainResPressurePSI;
159+
ControlActiveLocomotive.MainResPressurePSI = MainResPressurePSI;
160+
controlTrailerBrakeSystemSet = true; // Ensure this loop is only processes the first time update routine run
161+
MaximumMainReservoirPipePressurePSI = ControlActiveLocomotive.MaximumMainReservoirPipePressurePSI;
162+
CompressorRestartPressurePSI = ControlActiveLocomotive.CompressorRestartPressurePSI;
163+
MainResChargingRatePSIpS = ControlActiveLocomotive.MainResChargingRatePSIpS;
164+
BrakePipeChargingRatePSIorInHgpS = ControlActiveLocomotive.BrakePipeChargingRatePSIorInHgpS;
165+
TrainBrakePipeLeakPSIorInHgpS = ControlActiveLocomotive.TrainBrakePipeLeakPSIorInHgpS;
166+
}
167+
}
168+
164169
base.Update(elapsedClockSeconds);
165170
WheelSpeedMpS = SpeedMpS; // Set wheel speed for control car, required to make wheels go around.
166171

@@ -213,11 +218,45 @@ public override void Update(float elapsedClockSeconds)
213218
public override string GetStatus()
214219
{
215220
var status = new StringBuilder();
216-
if (HasGearController)
217-
status.AppendFormat("{0} = {1}\n", Simulator.Catalog.GetString("Gear"),
218-
ControlGearIndex < 0 ? Simulator.Catalog.GetParticularString("Gear", "N") : (ControlGearIndication).ToString());
219-
status.AppendLine();
220-
221+
status.AppendFormat("{0} = {1}\n",
222+
Simulator.Catalog.GetString("Battery switch"),
223+
LocomotivePowerSupply.BatterySwitch.On ? Simulator.Catalog.GetString("On") : Simulator.Catalog.GetString("Off"));
224+
status.AppendFormat("{0} = {1}\n",
225+
Simulator.Catalog.GetString("Master key"),
226+
LocomotivePowerSupply.MasterKey.On ? Simulator.Catalog.GetString("On") : Simulator.Catalog.GetString("Off"));
227+
if (ControlActiveLocomotive != null)
228+
{
229+
status.AppendLine();
230+
if (ControlActiveLocomotive is MSTSElectricLocomotive electric)
231+
{
232+
status.AppendFormat("{0} = ", Simulator.Catalog.GetString("Pantographs"));
233+
foreach (var pantograph in electric.Pantographs.List)
234+
status.AppendFormat("{0} ", Simulator.Catalog.GetParticularString("Pantograph", GetStringAttribute.GetPrettyName(pantograph.State)));
235+
status.AppendLine();
236+
status.AppendFormat("{0} = {1}\n",
237+
Simulator.Catalog.GetString("Circuit breaker"),
238+
Simulator.Catalog.GetParticularString("CircuitBreaker", GetStringAttribute.GetPrettyName(electric.ElectricPowerSupply.CircuitBreaker.State)));
239+
}
240+
else if (ControlActiveLocomotive is MSTSDieselLocomotive diesel)
241+
{
242+
status.AppendLine();
243+
status.AppendFormat("{0} = {1}\n", Simulator.Catalog.GetString("Engine"),
244+
Simulator.Catalog.GetParticularString("Engine", GetStringAttribute.GetPrettyName(diesel.DieselEngines[0].State)));
245+
if (HasGearController)
246+
status.AppendFormat("{0} = {1}\n", Simulator.Catalog.GetString("Gear"),
247+
ControlGearIndex < 0 ? Simulator.Catalog.GetParticularString("Gear", "N") : (ControlGearIndication).ToString());
248+
status.AppendFormat("{0} = {1}\n",
249+
Simulator.Catalog.GetString("Traction cut-off relay"),
250+
Simulator.Catalog.GetParticularString("TractionCutOffRelay", GetStringAttribute.GetPrettyName(diesel.DieselPowerSupply.TractionCutOffRelay.State)));
251+
}
252+
status.AppendFormat("{0} = {1}\n",
253+
Simulator.Catalog.GetString("Electric train supply"),
254+
ControlActiveLocomotive.LocomotivePowerSupply.ElectricTrainSupplySwitch.On ? Simulator.Catalog.GetString("On") : Simulator.Catalog.GetString("Off"));
255+
status.AppendLine();
256+
status.AppendFormat("{0} = {1}",
257+
Simulator.Catalog.GetParticularString("PowerSupply", "Power"),
258+
Simulator.Catalog.GetParticularString("PowerSupply", GetStringAttribute.GetPrettyName(ControlActiveLocomotive.LocomotivePowerSupply.MainPowerSupplyState)));
259+
}
221260
return status.ToString();
222261
}
223262

@@ -296,5 +335,69 @@ public override void ChangeGearDown()
296335
ControlGearUp = false;
297336
ControlGearDown = true;
298337
}
338+
public override float GetDataOf(CabViewControl cvc)
339+
{
340+
float data;
341+
switch (cvc.ControlType.Type)
342+
{
343+
// Locomotive controls
344+
case CABViewControlTypes.AMMETER:
345+
case CABViewControlTypes.AMMETER_ABS:
346+
case CABViewControlTypes.DYNAMIC_BRAKE_FORCE:
347+
case CABViewControlTypes.LOAD_METER:
348+
case CABViewControlTypes.ORTS_SIGNED_TRACTION_BRAKING:
349+
case CABViewControlTypes.ORTS_SIGNED_TRACTION_TOTAL_BRAKING:
350+
case CABViewControlTypes.TRACTION_BRAKING:
351+
case CABViewControlTypes.WHEELSLIP:
352+
data = ControlActiveLocomotive?.GetDataOf(cvc) ?? 0;
353+
break;
354+
// Diesel locomotive controls
355+
case CABViewControlTypes.FUEL_GAUGE:
356+
case CABViewControlTypes.ORTS_DIESEL_TEMPERATURE:
357+
case CABViewControlTypes.ORTS_OIL_PRESSURE:
358+
case CABViewControlTypes.ORTS_PLAYER_DIESEL_ENGINE:
359+
case CABViewControlTypes.ORTS_TRACTION_CUT_OFF_RELAY_AUTHORIZED:
360+
case CABViewControlTypes.ORTS_TRACTION_CUT_OFF_RELAY_CLOSED:
361+
case CABViewControlTypes.ORTS_TRACTION_CUT_OFF_RELAY_DRIVER_CLOSING_AUTHORIZATION:
362+
case CABViewControlTypes.ORTS_TRACTION_CUT_OFF_RELAY_DRIVER_CLOSING_ORDER:
363+
case CABViewControlTypes.ORTS_TRACTION_CUT_OFF_RELAY_DRIVER_OPENING_ORDER:
364+
case CABViewControlTypes.ORTS_TRACTION_CUT_OFF_RELAY_OPEN:
365+
case CABViewControlTypes.ORTS_TRACTION_CUT_OFF_RELAY_OPEN_AND_AUTHORIZED:
366+
case CABViewControlTypes.ORTS_TRACTION_CUT_OFF_RELAY_STATE:
367+
case CABViewControlTypes.RPM:
368+
case CABViewControlTypes.RPM_2:
369+
data = (ControlActiveLocomotive as MSTSDieselLocomotive)?.GetDataOf(cvc) ?? 0;
370+
break;
371+
// Electric locomotive controls
372+
case CABViewControlTypes.LINE_VOLTAGE:
373+
case CABViewControlTypes.ORTS_PANTOGRAPH_VOLTAGE_AC:
374+
case CABViewControlTypes.ORTS_PANTOGRAPH_VOLTAGE_DC:
375+
case CABViewControlTypes.PANTO_DISPLAY:
376+
case CABViewControlTypes.PANTOGRAPH:
377+
case CABViewControlTypes.PANTOGRAPH2:
378+
case CABViewControlTypes.ORTS_PANTOGRAPH3:
379+
case CABViewControlTypes.ORTS_PANTOGRAPH4:
380+
case CABViewControlTypes.PANTOGRAPHS_4:
381+
case CABViewControlTypes.PANTOGRAPHS_4C:
382+
case CABViewControlTypes.PANTOGRAPHS_5:
383+
case CABViewControlTypes.ORTS_VOLTAGE_SELECTOR:
384+
case CABViewControlTypes.ORTS_PANTOGRAPH_SELECTOR:
385+
case CABViewControlTypes.ORTS_POWER_LIMITATION_SELECTOR:
386+
case CABViewControlTypes.ORTS_CIRCUIT_BREAKER_DRIVER_CLOSING_ORDER:
387+
case CABViewControlTypes.ORTS_CIRCUIT_BREAKER_DRIVER_OPENING_ORDER:
388+
case CABViewControlTypes.ORTS_CIRCUIT_BREAKER_DRIVER_CLOSING_AUTHORIZATION:
389+
case CABViewControlTypes.ORTS_CIRCUIT_BREAKER_STATE:
390+
case CABViewControlTypes.ORTS_CIRCUIT_BREAKER_CLOSED:
391+
case CABViewControlTypes.ORTS_CIRCUIT_BREAKER_OPEN:
392+
case CABViewControlTypes.ORTS_CIRCUIT_BREAKER_AUTHORIZED:
393+
case CABViewControlTypes.ORTS_CIRCUIT_BREAKER_OPEN_AND_AUTHORIZED:
394+
data = (ControlActiveLocomotive as MSTSElectricLocomotive)?.GetDataOf(cvc) ?? 0;
395+
break;
396+
default:
397+
data = base.GetDataOf(cvc);
398+
break;
399+
}
400+
return data;
401+
}
299402
}
300403
}

0 commit comments

Comments
 (0)