Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion MechJeb2/MechJebModuleStageStats.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
extern alias JetBrainsAnnotations;
extern alias JetBrainsAnnotations;
using System.Collections.Generic;
using System.Diagnostics;
using MechJebLib.FuelFlowSimulation;
Expand All @@ -19,6 +19,10 @@ public class MechJebModuleStageStats : ComputerModule
public double AltSLT = 0;
public double Mach = 0;

public int HalfStageIndex => _vesselManagerVac.HalfStageIndex;
[Persistent(pass = (int)(Pass.TYPE | Pass.GLOBAL))]
public readonly EditableDoubleMult HalfStageEndMass = new EditableDoubleMult(0, 0.001);

private int _vabRebuildTimer = 1;

public readonly List<FuelStats> AtmoStats = new List<FuelStats>();
Expand Down Expand Up @@ -124,6 +128,7 @@ private void RunSimulation()
_vesselManagerVac.SetConditions(0, 0, 0);
_vesselManagerVac.SetInitial(VesselState.time, VesselState.orbitalPosition.WorldToV3Rotated(),
VesselState.orbitalVelocity.WorldToV3Rotated(), VesselState.forward.WorldToV3Rotated());
_vesselManagerVac.SetupStageAndAHalf(HalfStageEndMass);
_vesselManagerVac.StartFuelFlowSimulationJob();
}

Expand All @@ -133,6 +138,7 @@ private void RunSimulation()
_vesselManagerAtmo.SetConditions(atmDensity, staticPressureKpa * PhysicsGlobals.KpaToAtmospheres, mach);
_vesselManagerAtmo.SetInitial(VesselState.time, VesselState.orbitalPosition.WorldToV3Rotated(),
VesselState.orbitalVelocity.WorldToV3Rotated(), VesselState.forward.WorldToV3Rotated());
_vesselManagerAtmo.SetupStageAndAHalf(HalfStageEndMass);
_vesselManagerAtmo.StartFuelFlowSimulationJob();
}
}
Expand Down
7 changes: 6 additions & 1 deletion MechJeb2/MechJebModuleStagingController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,9 @@ public override void OnUpdate()
UpdateActiveModuleEngines(_allModuleEngines);
UpdateBurnedResources();

if (Vessel.currentStage == _stats.HalfStageIndex && Vessel.totalMass <= _stats.HalfStageEndMass)
Stage();

// don't decouple active or idle engines or tanks
if (InverseStageDecouplesActiveOrIdleEngineOrTank(Vessel.currentStage - 1, _burnedResources, _activeModuleEngines) &&
!InverseStageReleasesClamps(Vessel.currentStage - 1))
Expand All @@ -308,6 +311,7 @@ public override void OnUpdate()
if (!InverseStageHasActiveEngines(Vessel.currentStage))
{
Stage();
return;
}

// prevent staging when the current stage has active engines and the next stage has any engines (but not decouplers or clamps)
Expand All @@ -324,6 +328,7 @@ public override void OnUpdate()
if (InverseStageDecouplesDeactivatedEngineOrTank(Vessel.currentStage - 1))
{
Stage();
return;
}

// only decouple fairings if the dynamic pressure, altitude, and aerothermal flux conditions are respected
Expand Down Expand Up @@ -453,7 +458,7 @@ private double LastNonZeroDVStageBurnTime()
private bool InverseStageHasActiveEngines(int inverseStage)
{
foreach (ModuleEngines engine in _allModuleEngines)
if (engine.part.inverseStage == inverseStage && engine.EngineHasFuel())
if (engine.part.inverseStage >= inverseStage && engine.EngineHasFuel())
return true;
return false;
}
Expand Down
9 changes: 9 additions & 0 deletions MechJeb2/MechJebStageStatsHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,15 @@ public void AllStageStats()

Profiler.EndSample();

if (stats.HalfStageIndex != -1)
{
GUILayout.BeginHorizontal();
GUILayout.Label($"Half-stage index: {stats.HalfStageIndex}", GUILayout.Width(130));
GUILayout.Space(30);
GuiUtils.SimpleTextBox("End mass: ", stats.HalfStageEndMass, "kg");
GUILayout.EndHorizontal();
}

Profiler.BeginSample("AllStageStats.DrawColumns");

GUILayout.BeginHorizontal();
Expand Down
40 changes: 39 additions & 1 deletion MechJebLib/FuelFlowSimulation/FuelFlowSimulation.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
/*
/*
* Copyright Lamont Granquist, Sebastien Gaggini and the MechJeb contributors
* SPDX-License-Identifier: LicenseRef-PD-hp OR Unlicense OR CC0-1.0 OR 0BSD OR MIT-0 OR MIT OR LGPL-2.1+
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using MechJebLib.FuelFlowSimulation.PartModules;
using MechJebLib.Utils;
Expand All @@ -25,6 +26,7 @@ public class FuelFlowSimulation : BackgroundJob<bool>
private readonly HashSet<SimPart> _partsWithRCSDrains = new HashSet<SimPart>();
private readonly HashSet<SimPart> _partsWithRCSDrains2 = new HashSet<SimPart>();
private bool _allocatedFirstSegment;
private bool _halfStageIsDetected;

protected override bool Run(object? o)
{
Expand All @@ -34,6 +36,7 @@ protected override bool Run(object? o)
if (!(o is SimVessel vessel))
throw new ArgumentException("o is not a SimVessel", nameof(o));

_halfStageIsDetected = false;
_allocatedFirstSegment = false;
_time = 0;
Segments.Clear();
Expand All @@ -54,6 +57,9 @@ protected override bool Run(object? o)

_partsWithResourceDrains.Clear();

if (!_halfStageIsDetected)
vessel.HalfStageIndex = -1;

return true; // we pull results off the object not off the return value
}

Expand Down Expand Up @@ -112,12 +118,30 @@ private void SimulateStage(SimVessel vessel)
UpdateResourceDrainsAndResiduals(vessel);
double currentThrust = vessel.ThrustMagnitude;

if (!_halfStageIsDetected //is anyone insane enough to build a rocket with multiple half-stages? You never know
&& vessel.ActiveEngines.Count > 0
&& _sources.Count > 0)
{
int earliestDroppedEgineInStage = vessel.ActiveEngines.Max(x => x.Part.DecoupledInStage);
int earliestDroppedTankInStage = _sources.Max(x => x.DecoupledInStage);
if (earliestDroppedEgineInStage > earliestDroppedTankInStage)
{
_halfStageIsDetected = true;
vessel.HalfStageIndex = earliestDroppedEgineInStage + 1;
}
}

for (int steps = MAXSTEPS; steps > 0; steps--)
{
if (AllowedToStage(vessel))
return;

double dt = MinimumTimeStep();
if (_currentSegment.KSPStage == vessel.HalfStageIndex)
{
double massFlow = ResourceMaxMassFlow(vessel);
dt = Min(dt, (vessel.Mass - vessel.HalfStageEndMass) / massFlow);
}

// FIXME: if we have constructed a segment which is > 0 dV, but less than 0.02s, and there's a
// prior > 0dV segment in the same kspStage we should add those together to reduce clutter.
Expand Down Expand Up @@ -383,6 +407,17 @@ private double ResourceMaxTime()
return maxTime;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private double ResourceMaxMassFlow(SimVessel vessel)
{
double massFlow = 0;

foreach (SimModuleEngines engine in vessel.ActiveEngines)
massFlow += engine.MassFlowRate;

return massFlow;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void FinishRcsSegment(bool max, double deltaTime, double startMass, double endMass, double rcsThrust)
{
Expand Down Expand Up @@ -459,6 +494,9 @@ private static bool AllowedToStage(SimVessel vessel)
if (vessel.ActiveEngines.Count == 0)
return true;

if (vessel.CurrentStage == vessel.HalfStageIndex && vessel.Mass - vessel.HalfStageEndMass < 1e-6)
return true;

for (int i = 0; i < vessel.ActiveEngines.Count; i++)
{
SimModuleEngines e = vessel.ActiveEngines[i];
Expand Down
14 changes: 13 additions & 1 deletion MechJebLib/FuelFlowSimulation/SimVessel.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*
/*
* Copyright Lamont Granquist, Sebastien Gaggini and the MechJeb contributors
* SPDX-License-Identifier: LicenseRef-PD-hp OR Unlicense OR CC0-1.0 OR 0BSD OR MIT-0 OR MIT OR LGPL-2.1+
*/
Expand Down Expand Up @@ -46,6 +46,9 @@ public class SimVessel : IDisposable
public double T;
public V3 R, V, U;

public int HalfStageIndex = -1;
public double HalfStageEndMass = 0;

// CurrentStage gets scribbled over by the FuelFlowSimulation, SetCurrentStage() is intended to be used in
// the VesselBuilder and DecouplingAnalyzer to figure out the right value, ResetCurrentStage() is called by
// the VesselUpdater to reset it back.
Expand Down Expand Up @@ -80,6 +83,15 @@ public void SetInitial(double t, V3 r, V3 v, V3 u)
U = u;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetupStageAndAHalf(double endMass)
{
if (HalfStageIndex != -1)
{
HalfStageEndMass = endMass;
}
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void UpdateMass()
{
Expand Down
24 changes: 7 additions & 17 deletions MechJebLibBindings/FuelFlowSimulation/SimVesselBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*
/*
* Copyright Lamont Granquist, Sebastien Gaggini and the MechJeb contributors
* SPDX-License-Identifier: LicenseRef-PD-hp OR Unlicense OR CC0-1.0 OR 0BSD OR MIT-0 OR MIT OR LGPL-2.1+
*/
Expand Down Expand Up @@ -29,17 +29,9 @@ public class SimVesselBuilder

private static readonly CrewMass _crewMassDelegate;

private SimVessel _vessel
{
get => _manager._vessel;
set => _manager._vessel = value;
}
private SimVessel _vessel => _manager._vessel;

private IShipconstruct _kspVessel
{
get => _manager._kspVessel;
set => _manager._kspVessel = value;
}
private IShipconstruct _kspVessel => _manager._kspVessel;

private readonly SimVesselManager _manager;
private static readonly Type? _rfType;
Expand Down Expand Up @@ -68,7 +60,7 @@ static SimVesselBuilder()

private static double CrewMassNew(ProtoCrewMember crew) => PhysicsGlobals.KerbalCrewMass + crew.ResourceMass() + crew.InventoryMass();

public SimVesselBuilder(SimVesselManager manager)
internal SimVesselBuilder(SimVesselManager manager)
{
_manager = manager;
}
Expand Down Expand Up @@ -126,14 +118,12 @@ internal void UpdateSymmetryParts()
}
}

internal void BuildVessel(IShipconstruct kspVessel)
internal void BuildVessel()
{
_vessel.Dispose();
_vessel = SimVessel.Borrow();
_kspVessel = kspVessel;
BuildParts();
}

internal void BuildParts()
private void BuildParts()
{
_vessel.SetCurrentStage(StageManager.CurrentStage);

Expand Down
15 changes: 10 additions & 5 deletions MechJebLibBindings/FuelFlowSimulation/SimVesselManager.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*
/*
* Copyright Lamont Granquist, Sebastien Gaggini and the MechJeb contributors
* SPDX-License-Identifier: LicenseRef-PD-hp OR Unlicense OR CC0-1.0 OR 0BSD OR MIT-0 OR MIT OR LGPL-2.1+
*/
Expand All @@ -13,8 +13,6 @@ namespace MechJebLibBindings.FuelFlowSimulation
// need to link against KSP GameObjects (MechJebLibBindings.dll or something like that)
public partial class SimVesselManager
{
public List<FuelStats> Segments => FuelFlowSimulation.Segments;

private readonly SimVesselBuilder _builder;
private readonly SimVesselUpdater _updater;
private SimVessel _vessel;
Expand All @@ -31,6 +29,8 @@ public partial class SimVesselManager
public V3 V => _vessel.V;
public V3 U => _vessel.U;

public int HalfStageIndex => _vessel.HalfStageIndex;

public SimVesselManager()
{
_builder = new SimVesselBuilder(this);
Expand All @@ -41,9 +41,12 @@ public SimVesselManager()

public void Build(IShipconstruct vessel)
{
_vessel.Dispose();
_vessel = SimVessel.Borrow();
_kspVessel = vessel;

Clear();
_builder.BuildVessel(vessel);
_builder.BuildParts();
_builder.BuildVessel();
Update();
_builder.UpdateLinks();
_builder.UpdateCrossFeedSet();
Expand All @@ -59,6 +62,8 @@ public void SetConditions(double atmDensity, double atmPressure, double machNumb

public void SetInitial(double t, V3 r, V3 v, V3 u) => _vessel.SetInitial(t, r, v, u);

public void SetupStageAndAHalf(double endMass) => _vessel.SetupStageAndAHalf(endMass);

public void StartFuelFlowSimulationJob()
{
FuelFlowSimulation.DVLinearThrust = DVLinearThrust;
Expand Down
4 changes: 2 additions & 2 deletions MechJebLibBindings/FuelFlowSimulation/SimVesselUpdater.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*
/*
* Copyright Lamont Granquist, Sebastien Gaggini and the MechJeb contributors
* SPDX-License-Identifier: LicenseRef-PD-hp OR Unlicense OR CC0-1.0 OR 0BSD OR MIT-0 OR MIT OR LGPL-2.1+
*/
Expand Down Expand Up @@ -49,7 +49,7 @@ static SimVesselUpdater()
}
}

public SimVesselUpdater(SimVesselManager manager)
internal SimVesselUpdater(SimVesselManager manager)
{
_manager = manager;
}
Expand Down