Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
2 changes: 2 additions & 0 deletions docs/source/Support/bskReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ Version |release|
- ``ConfigureStopTime`` now supports specifying the stop condition as ``<=`` (default, prior behavior) or ``>=`` (new).
The new option is useful when the user wants to ensure that the simulation runs for at least the specified time,
instead of at most the specified time.
- Add the ``fuelLeakRate`` parameter to the :ref:`FuelTank` module to simulate fuel leaks that cause a loss of fuel mass
without imparting momentum.


Version 2.8.0 (August 30, 2025)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,5 +194,52 @@ def test_massDepletionTest(show_plots, thrusterConstructor):
err_msg="Thruster mass depletion not ramped up")
np.testing.assert_allclose(fuelMassDot[-1],0, rtol=1e-12, err_msg="Thruster mass depletion not ramped down")

def test_leakyTank():
"""Module Unit Test"""
scObject = spacecraft.Spacecraft()
scObject.ModelTag = "spacecraftBody"
unitTaskName = "unitTask"
unitProcessName = "TestProcess"

# Create a sim module as an empty container
unitTestSim = SimulationBaseClass.SimBaseClass()

# Create test thread
testProcessRate = macros.sec2nano(0.1)
testProc = unitTestSim.CreateNewProcess(unitProcessName)
testProc.addTask(unitTestSim.CreateNewTask(unitTaskName, testProcessRate))

# Make Fuel Tank
unitTestSim.fuelTankStateEffector = fuelTank.FuelTank()
tankModel = fuelTank.FuelTankModelConstantVolume()
unitTestSim.fuelTankStateEffector.setTankModel(tankModel)
tankModel.propMassInit = 40.0

# Add tank
scObject.addStateEffector(unitTestSim.fuelTankStateEffector)

# Make the tank leaky
leakRate = 1e-5 # kg/s
unitTestSim.fuelTankStateEffector.fuelLeakRate = leakRate # kg/s

# Add test module to runtime call list
unitTestSim.AddModelToTask(unitTaskName, unitTestSim.fuelTankStateEffector)
unitTestSim.AddModelToTask(unitTaskName, scObject)

fuelLog = unitTestSim.fuelTankStateEffector.fuelTankOutMsg.recorder()
unitTestSim.AddModelToTask(unitTaskName, fuelLog)
unitTestSim.InitializeSimulation()

stopTime = 1000.0
unitTestSim.ConfigureStopTime(macros.sec2nano(stopTime))
unitTestSim.ExecuteSimulation()

fuelMass = fuelLog.fuelMass
fuelMassDot = fuelLog.fuelMassDot

assert np.allclose(fuelMassDot, -leakRate, rtol=1e-6)
assert np.isclose(fuelMass[-1], 40.0 - stopTime * leakRate, rtol=1e-6)


if __name__ == "__main__":
test_massDepletionTest(True, thrusterDynamicEffector.ThrusterDynamicEffector)
1 change: 1 addition & 0 deletions src/simulation/dynamics/FuelTank/fuelTank.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ void FuelTank::updateEffectorMassProps(double integTime) {

// Mass depletion (call thrusters attached to this tank to get their mDot, and contributions)
this->fuelConsumption = 0.0;
this->fuelConsumption += this->fuelLeakRate;
for (auto &dynEffector: this->thrDynEffectors) {
dynEffector->computeStateContribution(integTime);
this->fuelConsumption += dynEffector->stateDerivContribution(0);
Expand Down
1 change: 1 addition & 0 deletions src/simulation/dynamics/FuelTank/fuelTank.h
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ class FuelTank :
bool updateOnly = true; //!< -- Sets whether to use update only mass depletion
Message<FuelTankMsgPayload> fuelTankOutMsg{}; //!< -- fuel tank output message name
FuelTankMsgPayload fuelTankMassPropMsg{}; //!< instance of messaging system message struct
double fuelLeakRate{}; //!< [kg/s] rate of fuel leaking from tank; does not produce force
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't want to just make this a public variable that gets set from python. I think it would be cleaner to have this as an optional input message. If it is connected, then we read in this rate and set this now private variable. This way, if the rate of fuel usage changes, this can be set via the input message?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you propose a new type of message to handle this? Currently the fuel tank takes no input messages since it's connected to the thrusters at a deeper level than the messaging system, so there's no obvious existing message type to include this in.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we can have a flowRate message type? This would make this implementation much more flexible.


private:
StateData *omegaState{}; //!< -- state data for omega_BN of the hub
Expand Down
Loading