Skip to content

Commit

Permalink
Add RCS stats to the stage stats display
Browse files Browse the repository at this point in the history
Works fairly similarly to KER, but knows about fuel flow and RCS
staging activation.  RCS drop tanks in stock shouldn't work correctly
at this point, need to have some kind of logic to quit the RCS
simulation early if all of the drainable RCS resources have been
drained from the parts that would drop after the next staging
activation.

Signed-off-by: Lamont Granquist <lamont@scriptkiddie.org>
  • Loading branch information
lamont-granquist committed Aug 4, 2023
1 parent 09cd44b commit 45710d6
Show file tree
Hide file tree
Showing 9 changed files with 330 additions and 260 deletions.
121 changes: 101 additions & 20 deletions MechJeb2/MechJebLib/Simulations/FuelFlowSimulation.cs
Expand Up @@ -19,6 +19,7 @@ public class FuelFlowSimulation : BackgroundJob<bool>
public bool DVLinearThrust = true; // include cos losses
private readonly HashSet<SimPart> _partsWithResourceDrains = new HashSet<SimPart>();
private readonly HashSet<SimPart> _partsWithRCSDrains = new HashSet<SimPart>();
private readonly HashSet<SimPart> _partsWithRCSDrains2 = new HashSet<SimPart>();
private bool _allocatedFirstSegment;

protected override bool Run(object? o)
Expand All @@ -34,9 +35,8 @@ protected override bool Run(object? o)

while (vessel.CurrentStage >= 0) // FIXME: should stop mutating vessel.CurrentStage
{
ComputeRCSMinValues(vessel);
SimulateStage(vessel);
ComputeRCSMaxValues(vessel);
ComputeRcsMaxValues(vessel);
FinishSegment(vessel);
vessel.Stage();
}
Expand All @@ -48,22 +48,55 @@ protected override bool Run(object? o)
return true; // we pull results off the object not off the return value
}

private void ComputeRCSMinValues(SimVessel vessel)
private void SimulateRCS(SimVessel vessel, bool max)
{
vessel.UpdateRCSStats();
vessel.UpdateActiveRCS();
UpdateRCSDrains(vessel);
double dt = MinimumRCSTimeStep();
vessel.SaveRcsStatus();
_partsWithRCSDrains2.Clear();

double lastmass = vessel.Mass;

int steps = MAXSTEPS;

while (true)
{
if (steps-- == 0)
throw new Exception("FuelFlowSimulation hit max steps of " + MAXSTEPS + " steps in rcs calculations");

vessel.UpdateRcsStats();
vessel.UpdateActiveRcs();
if (vessel.ActiveRcs.Count == 0)
break;

if (max)
Log("we've found some active engines in max");

UpdateRcsDrains(vessel);
double dt = MinimumRcsTimeStep();

if (max)
Log($"dt is {dt} in max");

ApplyRcsDrains(dt);
vessel.UpdateMass();
FinishRcsSegment(max, dt, lastmass, vessel.Mass, vessel.RcsThrust);
lastmass = vessel.Mass;
}

UnapplyRcsDrains();
vessel.ResetRcsStatus();
vessel.UpdateMass();
}

private void ComputeRCSMaxValues(SimVessel vessel)
private void UnapplyRcsDrains()
{
vessel.UpdateRCSStats();
vessel.UpdateActiveRCS();
UpdateRCSDrains(vessel);
double dt = MinimumRCSTimeStep();
foreach (SimPart p in _partsWithRCSDrains2)
p.UnapplyRCSDrains();
}

private void ComputeRcsMinValues(SimVessel vessel) => SimulateRCS(vessel, false);

private void ComputeRcsMaxValues(SimVessel vessel) => SimulateRCS(vessel, true);

private void SimulateStage(SimVessel vessel)
{
vessel.UpdateMass();
Expand All @@ -72,6 +105,7 @@ private void SimulateStage(SimVessel vessel)
UpdateResourceDrainsAndResiduals(vessel);

GetNextSegment(vessel);
ComputeRcsMinValues(vessel);
double currentThrust = vessel.ThrustMagnitude;

for (int steps = MAXSTEPS; steps > 0; steps--)
Expand All @@ -85,6 +119,7 @@ private void SimulateStage(SimVessel vessel)
// prior > 0dV segment in the same kspStage we should add those together to reduce clutter.
if (Math.Abs(vessel.ThrustMagnitude - currentThrust) > 1e-12)
{
ComputeRcsMaxValues(vessel);
FinishSegment(vessel);
GetNextSegment(vessel);
currentThrust = vessel.ThrustMagnitude;
Expand All @@ -102,23 +137,30 @@ private void SimulateStage(SimVessel vessel)
throw new Exception("FuelFlowSimulation hit max steps of " + MAXSTEPS + " steps");
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ApplyRcsDrains(double dt)
{
foreach (SimPart part in _partsWithRCSDrains)
part.ApplyRCSDrains(dt);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ApplyResourceDrains(double dt)
{
foreach (SimPart part in _partsWithResourceDrains)
part.ApplyResourceDrains(dt);
}

private void UpdateRCSDrains(SimVessel vessel)
private void UpdateRcsDrains(SimVessel vessel)
{
foreach (SimPart part in _partsWithRCSDrains)
part.ClearRCSDrains();

_partsWithRCSDrains.Clear();

for (int i = 0; i < vessel.ActiveRCS.Count; i++)
for (int i = 0; i < vessel.ActiveRcs.Count; i++)
{
SimModuleRCS e = vessel.ActiveRCS[i];
SimModuleRCS e = vessel.ActiveRcs[i];
foreach (int resourceId in e.PropellantFlowModes.Keys)
{
switch (e.PropellantFlowModes[resourceId])
Expand Down Expand Up @@ -194,6 +236,7 @@ private void UpdateRCSDrainsInParts(IList<SimPart> parts, double resourceConsump
private void UpdateRCSDrainsInPart(SimPart p, double resourceConsumption, int resourceId)
{
_partsWithRCSDrains.Add(p);
_partsWithRCSDrains2.Add(p);
p.AddRCSDrain(resourceId, resourceConsumption);
}

Expand Down Expand Up @@ -295,7 +338,7 @@ private static void UpdateResourceResidualsInParts(IList<SimPart> parts, double
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private double MinimumRCSTimeStep()
private double MinimumRcsTimeStep()
{
double maxTime = RCSMaxTime();

Expand Down Expand Up @@ -332,16 +375,54 @@ private double ResourceMaxTime()
return maxTime;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void FinishRcsSegment(bool max, double deltaTime, double startMass, double endMass, double rcsThrust)
{
Log($"deltatime: {deltaTime} startmass: {startMass} endmass: {endMass} rcsthrust: {rcsThrust}");

double rcsDeltaV = rcsThrust * deltaTime / (startMass - endMass) * Math.Log(startMass / endMass);
double rcsISP = rcsDeltaV / (G0 * Math.Log(startMass / endMass));

Log($"deltav: {rcsDeltaV} isp: {rcsISP}");

if (_currentSegment.RcsISP == 0)
_currentSegment.RcsISP = rcsISP;
if (_currentSegment.RcsThrust == 0)
_currentSegment.RcsThrust = rcsThrust;

if (max)
{
_currentSegment.MaxRcsDeltaV += rcsDeltaV;
if (_currentSegment.RcsStartTMR == 0)
_currentSegment.RcsStartTMR = rcsThrust / startMass;
}
else
{
_currentSegment.MinRcsDeltaV += rcsDeltaV;
_currentSegment.RcsEndTMR = _currentSegment.RcsThrust / endMass;
}

_currentSegment.RcsMass += startMass - endMass;
_currentSegment.RcsDeltaTime += deltaTime;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void FinishSegment(SimVessel vessel)
{
if (!_allocatedFirstSegment)
return;

_currentSegment.DeltaTime = _time - _currentSegment.StartTime;
_currentSegment.EndMass = vessel.Mass;

_currentSegment.ComputeStats();
double startMass = _currentSegment.StartMass;
double thrust = _currentSegment.Thrust;
double endMass = vessel.Mass;
double deltaTime = _time - _currentSegment.StartTime;
double deltaV = startMass > endMass ? thrust * deltaTime / (startMass - endMass) * Math.Log(startMass / endMass) : 0;
double isp = startMass > endMass ? deltaV / (G0 * Math.Log(startMass / endMass)) : 0;

_currentSegment.DeltaTime = deltaTime;
_currentSegment.EndMass = endMass;
_currentSegment.DeltaV = deltaV;
_currentSegment.Isp = isp;

Segments.Add(_currentSegment);
}
Expand Down
36 changes: 15 additions & 21 deletions MechJeb2/MechJebLib/Simulations/FuelStats.cs
@@ -1,6 +1,3 @@
using System;
using static MechJebLib.Utils.Statics;

#nullable enable

namespace MechJebLib.Simulations
Expand All @@ -17,29 +14,26 @@ public struct FuelStats
public double StartTime;
public double Thrust;
public double SpoolUpTime;
public double MaxRcsDeltaV;
public double MinRcsDeltaV;
public double RcsISP;
public double RcsDeltaTime;
public double RcsThrust;
public double RcsMass;
public double RcsStartTMR;
public double RcsEndTMR;

public double MaxAccel => EndMass > 0 ? Thrust / EndMass : 0;
public double ResourceMass => StartMass - EndMass;

public double StartTWR(double geeASL)
{
return StartMass > 0 ? Thrust / (9.80665 * geeASL * StartMass) : 0;
}
public double RcsStartTWR(double geeASL) => RcsStartTMR / (9.80665 * geeASL);
public double RcsMaxTWR(double geeASL) => RcsEndTMR / (9.80665 * geeASL);

public double MaxTWR(double geeASL)
{
return MaxAccel / (9.80665 * geeASL);
}
public double StartTWR(double geeASL) => StartMass > 0 ? Thrust / (9.80665 * geeASL * StartMass) : 0;

public void ComputeStats()
{
DeltaV = StartMass > EndMass ? Thrust * DeltaTime / (StartMass - EndMass) * Math.Log(StartMass / EndMass) : 0;
Isp = StartMass > EndMass ? DeltaV / (G0 * Math.Log(StartMass / EndMass)) : 0;
}
public double MaxTWR(double geeASL) => MaxAccel / (9.80665 * geeASL);

public override string ToString()
{
return
$"KSP Stage: {KSPStage.ToString()} Thrust: {Thrust.ToString()} Time: {DeltaTime.ToString()} StartMass: {StartMass.ToString()} EndMass: {EndMass.ToString()} DeltaV: {DeltaV.ToString()} ISP: {Isp.ToString()}";
}
public override string ToString() =>
$"KSP Stage: {KSPStage.ToString()} Thrust: {Thrust.ToString()} Time: {DeltaTime.ToString()} StartMass: {StartMass.ToString()} EndMass: {EndMass.ToString()} DeltaV: {DeltaV.ToString()} ISP: {Isp.ToString()}";
}
}
27 changes: 14 additions & 13 deletions MechJeb2/MechJebLib/Simulations/PartModules/SimModuleRCS.cs
Expand Up @@ -4,7 +4,6 @@
using System.Runtime.CompilerServices;
using MechJebLib.Primitives;
using MechJebLib.Utils;
using static MechJebLib.Utils.Statics;

namespace MechJebLib.Simulations.PartModules
{
Expand All @@ -17,14 +16,15 @@ public class SimModuleRCS : SimPartModule

public readonly H1 AtmosphereCurve = H1.Get(true);

public double G;
public double Isp;
public double Thrust;
public bool RcsEnabled;
public double ISPMult;
public double ThrustPercentage;
public double MaxFuelFlow;
public double MassFlowRate;
public double G;
public double Isp;
public double Thrust;
public bool RcsEnabled;
private bool _savedRcsEnabled;
public double ISPMult;
public double ThrustPercentage;
public double MaxFuelFlow;
public double MassFlowRate;

private double _atmPressure => Part.Vessel.ATMPressure;

Expand All @@ -48,6 +48,10 @@ public void UpdateRCSStatus()
RcsEnabled = false;
}

public void SaveStatus() => _savedRcsEnabled = RcsEnabled;

public void ResetStatus() => RcsEnabled = _savedRcsEnabled;

// FIXME: aggressively duplicates ModuleEngines code and should be moved to SimPart
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private bool CanDrawResources()
Expand Down Expand Up @@ -110,10 +114,7 @@ public void Update()
SetConsumptionRates();
}

public void Activate()
{
RcsEnabled = true;
}
public void Activate() => RcsEnabled = true;

private static void Clear(SimModuleRCS m)
{
Expand Down
18 changes: 18 additions & 0 deletions MechJeb2/MechJebLib/Simulations/SimPart.cs
Expand Up @@ -104,6 +104,24 @@ public void ApplyResourceDrains(double dt)
Resources[id] = Resources[id].Drain(dt * _resourceDrains[id]);
}

public void ApplyRCSDrains(double dt)
{
foreach (int id in _rcsDrains.Keys)
Resources[id] = Resources[id].RCSDrain(dt * _rcsDrains[id]);
}

private readonly List<int> _resourceKeys = new List<int>();

public void UnapplyRCSDrains()
{
_resourceKeys.Clear();
foreach (int id in Resources.Keys)
_resourceKeys.Add(id);

foreach (int id in _resourceKeys)
Resources[id] = Resources[id].ResetRCS();
}

public void UpdateResourceResidual(double residual, int resourceId)
{
if (!Resources.TryGetValue(resourceId, out SimResource resource))
Expand Down
41 changes: 33 additions & 8 deletions MechJeb2/MechJebLib/Simulations/SimResource.cs
@@ -1,22 +1,47 @@
using static MechJebLib.Utils.Statics;

#nullable enable

namespace MechJebLib.Simulations
{
public struct SimResource
{
public bool Free;
public double MaxAmount;
public double Amount;
public int Id;
public double Density;
public double Residual;
public bool Free;
public double MaxAmount;
private double _amount;

public double Amount
{
get => _amount + _rcsAmount;
set => _amount = value;
}

private double _rcsAmount;
public int Id;
public double Density;
public double Residual;

public double ResidualThreshold => Residual * MaxAmount;

public SimResource Drain(double resourceDrain)
{
Amount -= resourceDrain;
if (Amount < 0) Amount = 0;
_amount -= resourceDrain;
if (_amount < 0) _amount = 0;
return this;
}

public SimResource RCSDrain(double rcsDrain)
{
_rcsAmount -= rcsDrain;
if (Amount < 0) _rcsAmount = _amount;
Log($"RCSDrain: {rcsDrain} _amount: {_amount} _rcsAmount: {_rcsAmount}");

return this;
}

public SimResource ResetRCS()
{
_rcsAmount = 0;
return this;
}
}
Expand Down

0 comments on commit 45710d6

Please sign in to comment.