Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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: 1 addition & 1 deletion .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ jobs:
timeout-minutes: 75
strategy:
matrix:
python-version: [ "3.11", "3.12" ]
python-version: [ "3.11", "3.12", "3.13" ]
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion docs/source/Install/installOnLinux.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Software setup

In order to run Basilisk, the following software will be necessary. This document outline how to install this support software.

- `Python <https://www.python.org/>`__ 3.8 to 3.12
- `Python <https://www.python.org/>`__ 3.8 to 3.13
- `SWIG <http://www.swig.org/>`__ (version 4.x)
- `GCC <https://gcc.gnu.org/>`__
- (Optional) Get the `GitKraken <https://www.gitkraken.com>`__
Expand Down
2 changes: 1 addition & 1 deletion docs/source/Install/installOnMacOS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Setup On macOS
==============

These instruction outline how to install Basilisk (BSK) on a clean version of macOS.
Basilisk requires the use of Python 3.8 to 3.12.
Basilisk requires the use of Python 3.8 to 3.13.

The following python package dependencies are automatically checked and installed in the steps below.

Expand Down
2 changes: 1 addition & 1 deletion docs/source/Install/installOnWindows.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Software setup

In order to run Basilisk, the following software will be necessary:

- `Python <https://www.python.org/downloads/windows/>`__ 3.8 to 3.12
- `Python <https://www.python.org/downloads/windows/>`__ 3.8 to 3.13
- `pip <https://pip.pypa.io/en/stable/installing/>`__
- Visual Studios 15 2017 or greater
- `Swig <http://www.swig.org/download.html>`__ version 4.X
Expand Down
3 changes: 3 additions & 0 deletions docs/source/Support/bskReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ Version |release|
and conversions.
- Updated install requirements to not manually install ``cmake``, but have it installed with pip by including it
in ``requirements_dev.txt``. A ``conan`` dependency requires Basilisk to use ``cmake<4.0`` for now.
- Add support for python 3.13 by removing the use of ``eval()`` and most ``exec()`` methods,
rewrote ``methodizeEvent()`` in ``SimulationBaseClass.py``. If you use python 3.13+ the
scope of the ``eval()`` method has changed (see https://peps.python.org/pep-0667/).


Version 2.6.0 (Feb. 21, 2025)
Expand Down
19 changes: 9 additions & 10 deletions examples/MonteCarloExamples/scenarioRerunMonteCarlo.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@


"""

import inspect
import os
import sys
import importlib

from Basilisk.utilities.MonteCarlo.Controller import Controller
from Basilisk.utilities.MonteCarlo.RetentionPolicy import RetentionPolicy
Expand All @@ -53,7 +53,6 @@ def run(time=None):
3) Provide the run numbers you wish to rerun

4) Add any new retention policies to the bottom

"""

# Step 1-3: Change to the relevant scenario
Expand All @@ -68,12 +67,15 @@ def run(time=None):
icName = path + "/" + mcName # Use MC script name for directory
newDataDir = path + "/" + mcName + "/rerun"

# Import the base scenario module, not the MC script
exec('import '+ scenarioName)
simulationModule = eval(scenarioName + ".scenario_AttFeedback") # Use the actual scenario function
# Use importlib to import the scenario module
scenarioModule = importlib.import_module(scenarioName)

# Access the class and methods dynamically using getattr()
simulationModule = getattr(scenarioModule, scenarioName)

if time is not None:
exec (scenarioName + '.scenario_AttFeedback.simBaseTime = time')
executionModule = eval(scenarioName + ".runScenario")
simulationModule.simBaseTime = time
executionModule = getattr(scenarioModule, "runScenario")

monteCarlo.setSimulationFunction(simulationModule)
monteCarlo.setExecutionFunction(executionModule)
Expand All @@ -84,18 +86,15 @@ def run(time=None):
monteCarlo.setShouldDisperseSeeds(False)
monteCarlo.shouldArchiveParameters = False


# Step 4: Add any additional retention policies desired
retentionPolicy = RetentionPolicy()
retentionPolicy.logRate = int(2E9)
retentionPolicy.addMessageLog("attGuidMsg", ["sigma_BR"])
monteCarlo.addRetentionPolicy(retentionPolicy)


failed = monteCarlo.runInitialConditions(runsList)
assert len(failed) == 0, "Should run ICs successfully"



if __name__ == "__main__":
run()
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ requires = [
[project]
name = 'Basilisk'
dynamic = ["version", "dependencies"]
requires-python = ">=3.8, <3.13"
requires-python = ">=3.8, <3.14"

readme = "README.md"
license = {file = "LICENSE"}
Expand Down
7 changes: 6 additions & 1 deletion src/architecture/_GeneralModuleFiles/swig_conly_data.i
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,12 @@ ARRAY2ASLIST(bool, PyBool_FromLong, PyObject_IsTrue)

def getStructSize(self):
try:
return eval('sizeof_' + repr(self).split(';')[0].split('.')[-1])
class_name = repr(self).split(';')[0].split('.')[-1]
sizeof_variable_name = 'sizeof_' + class_name
size = globals().get(sizeof_variable_name)

if size is None:
raise ValueError(f"{sizeof_variable_name} not found in globals()")
except (NameError) as e:
typeString = 'sizeof_' + repr(self).split(';')[0].split('.')[-1]
raise NameError(e.message + '\nYou tried to get this size macro: ' + typeString +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ void Update_mtbMomentumManagementSimple(mtbMomentumManagementSimpleConfig *confi
* Read the input message and initialize output message.
*/
RWSpeedMsgPayload rwSpeedsInMsgBuffer = RWSpeedMsg_C_read(&configData->rwSpeedsInMsg);
CmdTorqueBodyMsgPayload tauMtbRequestOutMsgBuffer = CmdTorqueBodyMsg_C_zeroMsgPayload(&configData->tauMtbRequestOutMsg);
CmdTorqueBodyMsgPayload tauMtbRequestOutMsgBuffer = CmdTorqueBodyMsg_C_zeroMsgPayload();

/*! - Compute wheel momentum in Body frame components by calculating it first in the wheel frame and then
transforming it from the wheel space into the body frame using Gs.*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,13 @@ def setupFilterData(filterObject):
])
def test_all_sunline_kf(show_plots, function):
"""Module Unit Test"""
[testResults, testMessage] = eval(function + '(show_plots)')
testFunction = globals().get(function)

if testFunction is None:
raise ValueError(f"Function '{function}' not found in global scope")

[testResults, testMessage] = testFunction(show_plots)

assert testResults < 1, testMessage


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,12 @@
])
def test_all_test_eulerRotation(show_plots, function):
"""Module Unit Test"""
[testResults, testMessage] = eval(function + '(show_plots)')
testFunction = globals().get(function)

if testFunction is None:
raise ValueError(f"Function '{function}' not found in global scope")

[testResults, testMessage] = testFunction(show_plots)
assert testResults < 1, testMessage


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,12 @@
])
def test_stateArchitectureAllTests(show_plots, function):
"""Module Unit Test"""
[testResults, testMessage] = eval(function + '(show_plots)')
testFunction = globals().get(function)

if testFunction is None:
raise ValueError(f"Function '{function}' not found in global scope")

[testResults, testMessage] = testFunction(show_plots)
assert testResults < 1, testMessage


Expand Down Expand Up @@ -321,4 +326,4 @@ def subModuleTestFunction2(show_plots):
#
if __name__ == "__main__":
# all_inertial3DSpin(False)
subModuleTestFunction2(False)
subModuleTestFunction2(False)
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ void Update_dipoleMapping(dipoleMappingConfig *configData, uint64_t callTime, in
* Read the input messages and initialize output message.
*/
DipoleRequestBodyMsgPayload dipoleRequestBodyInMsgBuffer = DipoleRequestBodyMsg_C_read(&configData->dipoleRequestBodyInMsg);
MTBCmdMsgPayload dipoleRequestMtbOutMsgBuffer = MTBCmdMsg_C_zeroMsgPayload(&configData->dipoleRequestMtbOutMsg);
MTBCmdMsgPayload dipoleRequestMtbOutMsgBuffer = MTBCmdMsg_C_zeroMsgPayload();

/*! - Map the requested Body frame dipole request to individual torque rod dipoles.*/
mMultV(configData->steeringMatrix, configData->mtbArrayConfigParams.numMTB, 3, dipoleRequestBodyInMsgBuffer.dipole_B, dipoleRequestMtbOutMsgBuffer.mtbDipoleCmds);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,12 @@
])
def test_chebyPosFitAllTest(show_plots, function):
"""Module Unit Test"""
[testResults, testMessage] = eval(function + '(show_plots)')
testFunction = globals().get(function)

if testFunction is None:
raise ValueError(f"Function '{function}' not found in global scope")

[testResults, testMessage] = testFunction(show_plots)
assert testResults < 1, testMessage


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,12 @@
])
def test_hingedRigidBody(show_plots, function):
"""Module Unit Test"""
[testResults, testMessage] = eval(function + '(show_plots)')
testFunction = globals().get(function)

if testFunction is None:
raise ValueError(f"Function '{function}' not found in global scope")

[testResults, testMessage] = testFunction(show_plots)
assert testResults < 1, testMessage

@pytest.mark.parametrize("useScPlus", [True, False])
Expand Down Expand Up @@ -296,18 +301,18 @@ def hingedRigidBodyNoGravity(show_plots):
# --fulltrace command line option is specified.
__tracebackhide__ = True

testFailCount = 0 # zero unit test result counter
testFailCount = 0 # zero unit test result counter
testMessages = [] # create empty list to store test log messages

scObject = spacecraftSystem.SpacecraftSystem()
scObject.ModelTag = "spacecraftBody"

unitTaskName = "unitTask" # arbitrary name (don't change)
unitProcessName = "TestProcess" # arbitrary name (don't change)

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

# Create test thread
testProcessRate = macros.sec2nano(0.001) # update process rate update time
testProc = unitTestSim.CreateNewProcess(unitProcessName)
Expand Down Expand Up @@ -360,7 +365,7 @@ def hingedRigidBodyNoGravity(show_plots):

dataLog = scObject.primaryCentralSpacecraft.scStateOutMsg.recorder()
unitTestSim.AddModelToTask(unitTaskName, dataLog)

scLog = pythonVariableLogger.PythonVariableLogger({
"totOrbEnergy": lambda _: scObject.primaryCentralSpacecraft.totOrbEnergy,
"totOrbAngMomPntN_N": lambda _: scObject.primaryCentralSpacecraft.totOrbAngMomPntN_N,
Expand Down Expand Up @@ -878,7 +883,7 @@ def hingedRigidBodyThetaSS(show_plots):
PlotTitle = "BOE Calculation for Steady State Theta 2 Deflection vs Simulation"
format = r"width=0.8\textwidth"
unitTestSupport.writeFigureLaTeX(PlotName, PlotTitle, plt, format, path)

if show_plots:
plt.show()
plt.close("all")
Expand Down Expand Up @@ -1878,4 +1883,4 @@ class boxAndWingParameters:
# test_hingedRigidBodyThetaSS(True)
# test_hingedRigidBodyFrequencyAmp(True)
# test_hingedRigidBodyMotorTorque(True, True)
hingedRigidBodyLagrangVsBasilisk(True)
hingedRigidBodyLagrangVsBasilisk(True)
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,7 @@ def run(doUnitTests, show_plots, integratorCase):
#
np.set_printoptions(precision=16)
fileNameString = filename[len(path) + 6:-3]
if integratorCase == "bogackiShampine":
plt.close("all") # clears out plots from earlier test runs
plt.close("all") # clears out plots from earlier test runs

# draw orbit in perifocal frame
b = oe.a * np.sqrt(1 - oe.e * oe.e)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,13 @@ def test_constraintEffector(show_plots, function):

"""

eval(function + '(show_plots)')
testFunction = globals().get(function)

if testFunction is None:
raise ValueError(f"Function '{function}' not found in global scope")

result = testFunction(show_plots)


def constraintEffectorOrbitalConservation(show_plots):

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,13 @@
])
def test_ForceBodyAndTorqueAllTest(show_plots, function):
"""Module Unit Test"""
[testResults, testMessage] = eval(function + '()')
testFunction = globals().get(function)

if testFunction is None:
raise ValueError(f"Function '{function}' not found in global scope")

[testResults, testMessage] = testFunction()

assert testResults < 1, testMessage


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,12 @@
])
def test_gravityEffectorAllTest(show_plots, function):
"""Module Unit Test"""
[testResults, testMessage] = eval(function + '(show_plots)')
testFunction = globals().get(function)

if testFunction is None:
raise ValueError(f"Function '{function}' not found in global scope")

[testResults, testMessage] = testFunction(show_plots)
assert testResults < 1, testMessage


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,12 @@ def test_translatingBody(show_plots, function):

against their initial values.
"""
eval(function + '(show_plots)')
testFunction = globals().get(function)

if testFunction is None:
raise ValueError(f"Function '{function}' not found in global scope")

testFunction(show_plots)

def translatingBodyNoInput(show_plots):
r"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,18 @@ def test_translatingBody(show_plots, function):

should be constant when tested against their initial values.
"""

func = globals().get(function)

if func is None:
raise ValueError(f"Function '{function}' not found in global scope")

if function == "translatingBodyCommandedForce":
eval(function + '(show_plots, 1.0)')
func(show_plots, 1.0)
elif function == "translatingBodyRhoReference":
eval(function + '(show_plots, 0.5)')
func(show_plots, 0.5)
else:
eval(function + '(show_plots)')
func(show_plots)


# rho ref and cmd force are zero, no lock flag
Expand Down
14 changes: 10 additions & 4 deletions src/simulation/dynamics/spacecraft/_UnitTest/test_spacecraft.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,18 @@ def addTimeColumn(time, data):
])
def test_spacecraftAllTest(show_plots, function):
"""Module Unit Test"""
func = globals().get(function)

if func is None:
raise ValueError(f"Function '{function}' not found in global scope")

if function == "scOptionalRef":
[testResults, testMessage] = eval(function + '(show_plots, 1e-3)')
elif function == "scAccumDV" or function == "scAccumDVExtForce":
[testResults, testMessage] = eval(function + '()')
[testResults, testMessage] = func(show_plots, 1e-3)
elif function in ["scAccumDV", "scAccumDVExtForce"]:
[testResults, testMessage] = func()
else:
[testResults, testMessage] = eval(function + '(show_plots)')
[testResults, testMessage] = func(show_plots)

assert testResults < 1, testMessage


Expand Down
Loading