Skip to content

Commit 3186040

Browse files
committed
Add battery subsystem
1 parent 6559a09 commit 3186040

File tree

15 files changed

+203
-61
lines changed

15 files changed

+203
-61
lines changed

Source/Orts.Formats.Msts/CabViewFile.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ public enum CABViewControlTypes
8383
LINE_VOLTAGE,
8484
ORTS_PANTOGRAPH_VOLTAGE_AC,
8585
ORTS_PANTOGRAPH_VOLTAGE_DC,
86+
ORTS_BATTERY_VOLTAGE,
8687
AMMETER,
8788
AMMETER_ABS,
8889
LOAD_METER,

Source/Orts.Parsers.Msts/STFReader.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -815,6 +815,12 @@ public enum UNITS
815815
/// </summary>
816816
Angle = 1 << 28,
817817

818+
/// <summary>
819+
/// Valid Units: J, kJ, MJ, Wh, kWh
820+
/// <para>Scaled to J.</para>
821+
/// </summary>
822+
Energy = 1 << 29,
823+
818824
// "Any" is used where units cannot easily be specified, such as generic routines for interpolating continuous data from point values.
819825
// or interpreting locomotive cab attributes from the ORTSExtendedCVF experimental mechanism.
820826
// "Any" should not be used where the dimensions of a unit are predictable.
@@ -1145,6 +1151,17 @@ internal double ParseUnitSuffix(ref string constant, UNITS validUnits)
11451151
case "rad": return 1;
11461152
case "deg": return 0.0174533; // 1 deg = 0.0174533 radians
11471153
}
1154+
1155+
if ((validUnits & UNITS.Energy) > 0)
1156+
switch (suffix)
1157+
{
1158+
case "": return 1.0f;
1159+
case "j": return 1;
1160+
case "kj": return 1000;
1161+
case "mj": return 1e6f;
1162+
case "wh": return 3.6e3f;
1163+
case "kwh": return 3.6e6f;
1164+
}
11481165
STFException.TraceWarning(this, "Found a suffix '" + suffix + "' which could not be parsed as a " + validUnits.ToString() + " unit");
11491166
return 1;
11501167
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ internal void AttachToHost(IPowerSupply host)
4949
/// Current state of the battery
5050
/// </summary>
5151
public PowerSupplyState CurrentBatteryState() => Host.BatteryState;
52+
public float BatteryVoltageV => Host.Battery.VoltageV;
5253

5354
/// <summary>
5455
/// True if the battery is switched on

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,7 @@ public override void Parse(string lowercasetoken, STFReader stf)
8989
case "engine(ortspowersupplyparameters":
9090
case "engine(ortstractioncutoffrelay":
9191
case "engine(ortstractioncutoffrelayclosingdelay":
92-
case "engine(ortsbattery(mode":
93-
case "engine(ortsbattery(delay":
94-
case "engine(ortsbattery(defaulton":
92+
case "engine(ortsbattery":
9593
case "engine(ortsmasterkey(mode":
9694
case "engine(ortsmasterkey(delayoff":
9795
case "engine(ortsmasterkey(headlightcontrol":

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,7 @@ public override void Parse(string lowercasetoken, STFReader stf)
150150
case "engine(ortspowersupplyparameters":
151151
case "engine(ortstractioncutoffrelay":
152152
case "engine(ortstractioncutoffrelayclosingdelay":
153-
case "engine(ortsbattery(mode":
154-
case "engine(ortsbattery(delay":
155-
case "engine(ortsbattery(defaulton":
153+
case "engine(ortsbattery":
156154
case "engine(ortsmasterkey(mode":
157155
case "engine(ortsmasterkey(delayoff":
158156
case "engine(ortsmasterkey(headlightcontrol":

Source/Orts.Simulation/Simulation/RollingStocks/MSTSElectricLocomotive.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,7 @@ public override void Parse(string lowercasetoken, STFReader stf)
7070
case "engine(ortspowersupplyparameters":
7171
case "engine(ortscircuitbreaker":
7272
case "engine(ortscircuitbreakerclosingdelay":
73-
case "engine(ortsbattery(mode":
74-
case "engine(ortsbattery(delay":
75-
case "engine(ortsbattery(defaulton":
73+
case "engine(ortsbattery":
7674
case "engine(ortsmasterkey(mode":
7775
case "engine(ortsmasterkey(delayoff":
7876
case "engine(ortsmasterkey(headlightcontrol":

Source/Orts.Simulation/Simulation/RollingStocks/MSTSLocomotive.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6095,6 +6095,10 @@ public virtual float GetDataOf(CabViewControl cvc)
60956095
data = LocomotivePowerSupply.BatterySwitch.On ? 1 : 0;
60966096
break;
60976097

6098+
case CABViewControlTypes.ORTS_BATTERY_VOLTAGE:
6099+
data = LocomotivePowerSupply.BatteryVoltageV;
6100+
break;
6101+
60986102
case CABViewControlTypes.ORTS_MASTER_KEY:
60996103
data = LocomotivePowerSupply.MasterKey.CommandSwitch ? 1 : 0;
61006104
break;

Source/Orts.Simulation/Simulation/RollingStocks/MSTSSteamLocomotive.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,9 +1056,7 @@ public override void Parse(string lowercasetoken, STFReader stf)
10561056
IsSelectGeared = String.Compare(typeString2, "Select") == 0;
10571057
break;
10581058

1059-
case "engine(ortsbattery(mode":
1060-
case "engine(ortsbattery(delay":
1061-
case "engine(ortsbattery(defaulton":
1059+
case "engine(ortsbattery":
10621060
case "engine(ortsmasterkey(mode":
10631061
case "engine(ortsmasterkey(delayoff":
10641062
case "engine(ortsmasterkey(headlightcontrol":

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1592,9 +1592,7 @@ public virtual void Parse(string lowercasetoken, STFReader stf)
15921592
break;
15931593
case "wagon(ortspowersupply":
15941594
case "wagon(ortspowerondelay":
1595-
case "wagon(ortsbattery(mode":
1596-
case "wagon(ortsbattery(delay":
1597-
case "wagon(ortsbattery(defaulton":
1595+
case "wagon(ortsbattery":
15981596
case "wagon(ortspowersupplycontinuouspower":
15991597
case "wagon(ortspowersupplyheatingpower":
16001598
case "wagon(ortspowersupplyairconditioningpower":
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
2+
using Microsoft.CodeAnalysis.VisualBasic.Syntax;
3+
using Microsoft.Xna.Framework;
4+
using Orts.Common;
5+
using Orts.Parsers.Msts;
6+
using ORTS.Scripting.Api;
7+
using System;
8+
using System.Collections.Generic;
9+
using System.Diagnostics;
10+
using System.IO;
11+
using System.Linq;
12+
using Event = Orts.Common.Event;
13+
14+
namespace Orts.Simulation.RollingStocks.SubSystems.PowerSupplies
15+
{
16+
public class Battery : ISubSystem<Battery>
17+
{
18+
public BatterySwitch BatterySwitch { get; protected set; }
19+
public float NominalVoltageV = 72;
20+
public float VoltageV { get; protected set; }
21+
public float CurrentCapacityJ { get; protected set; }
22+
public float MaxCapacityJ = 3.6e7f;
23+
protected float EnergyFlowW; // < 0 discharging, > 0 charging
24+
public Interpolator ChargeVoltageCurve;
25+
public PowerSupplyState State;
26+
public Battery(MSTSWagon wagon)
27+
{
28+
BatterySwitch = new BatterySwitch(wagon);
29+
}
30+
public virtual void Parse(string lowercasetoken, STFReader stf)
31+
{
32+
switch (lowercasetoken)
33+
{
34+
case "engine(ortsbattery":
35+
case "wagon(ortsbattery":
36+
stf.MustMatch("(");
37+
while (!stf.EndOfBlock())
38+
{
39+
lowercasetoken = stf.ReadItem().ToLower();
40+
switch (lowercasetoken)
41+
{
42+
case "voltage":
43+
NominalVoltageV = stf.ReadFloatBlock(STFReader.UNITS.Voltage, NominalVoltageV);
44+
break;
45+
case "maxcapacity":
46+
MaxCapacityJ = stf.ReadFloatBlock(STFReader.UNITS.Energy, MaxCapacityJ);
47+
break;
48+
case "chargevoltagecurve":
49+
ChargeVoltageCurve = new Interpolator(stf);
50+
break;
51+
case "mode":
52+
case "delay":
53+
case "defaulton":
54+
BatterySwitch.Parse(lowercasetoken, stf);
55+
break;
56+
case "(":
57+
stf.SkipRestOfBlock();
58+
break;
59+
}
60+
}
61+
break;
62+
}
63+
}
64+
public virtual void Copy(Battery other)
65+
{
66+
BatterySwitch.Copy(other.BatterySwitch);
67+
NominalVoltageV = other.NominalVoltageV;
68+
MaxCapacityJ = other.MaxCapacityJ;
69+
ChargeVoltageCurve = other?.ChargeVoltageCurve;
70+
}
71+
public virtual void Initialize()
72+
{
73+
CurrentCapacityJ = MaxCapacityJ;
74+
if (ChargeVoltageCurve == null)
75+
{
76+
ChargeVoltageCurve = new Interpolator(new float[] {0, MaxCapacityJ}, new float[] {0, NominalVoltageV});
77+
}
78+
79+
BatterySwitch.Initialize();
80+
}
81+
public virtual void InitializeMoving()
82+
{
83+
BatterySwitch.InitializeMoving();
84+
}
85+
public virtual void Save(BinaryWriter outf)
86+
{
87+
BatterySwitch.Save(outf);
88+
outf.Write(CurrentCapacityJ);
89+
outf.Write(EnergyFlowW);
90+
}
91+
public virtual void Restore(BinaryReader inf)
92+
{
93+
BatterySwitch.Restore(inf);
94+
CurrentCapacityJ = inf.ReadSingle();
95+
EnergyFlowW = inf.ReadSingle();
96+
}
97+
public virtual void Update(float elapsedClockSeconds)
98+
{
99+
BatterySwitch.Update(elapsedClockSeconds);
100+
101+
CurrentCapacityJ = MathHelper.Clamp(CurrentCapacityJ + EnergyFlowW * elapsedClockSeconds, 0, MaxCapacityJ);
102+
VoltageV = ChargeVoltageCurve[CurrentCapacityJ];
103+
}
104+
105+
}
106+
}

0 commit comments

Comments
 (0)