From 11c1d312b5f2077adac1a519d83c8b7274b70902 Mon Sep 17 00:00:00 2001
From: weasdown <34220924+weasdown@users.noreply.github.com>
Date: Sun, 9 Feb 2025 11:12:49 +0000
Subject: [PATCH 1/7] Create python-package.yml
Add configuration for Python packaging.
---
.github/workflows/python-package.yml | 40 ++++++++++++++++++++++++++++
1 file changed, 40 insertions(+)
create mode 100644 .github/workflows/python-package.yml
diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml
new file mode 100644
index 0000000..1b85a0f
--- /dev/null
+++ b/.github/workflows/python-package.yml
@@ -0,0 +1,40 @@
+# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
+# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
+
+name: Python package
+
+on:
+ push:
+ branches: [ "main" ]
+ pull_request:
+ branches: [ "main" ]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
+
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up Python ${{ matrix.python-version }}
+ uses: actions/setup-python@v3
+ with:
+ python-version: ${{ matrix.python-version }}
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ python -m pip install flake8 pytest
+ if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
+ - name: Lint with flake8
+ run: |
+ # stop the build if there are Python syntax errors or undefined names
+ flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
+ # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
+ flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
+ - name: Test with pytest
+ run: |
+ pytest
From b86c1ba0c09610555a89c7ff521e5a33a016e85a Mon Sep 17 00:00:00 2001
From: weasdown <34220924+weasdown@users.noreply.github.com>
Date: Tue, 12 Aug 2025 09:39:39 +0100
Subject: [PATCH 2/7] feat: squash merge main
---
.idea/GMAT-Python-simple.iml | 10 +
.idea/inspectionProfiles/Project_Default.xml | 33 ++++
.../inspectionProfiles/profiles_settings.xml | 6 +
.idea/misc.xml | 10 +
.../001_Creating_a_Spacecraft.xml | 25 +++
.../Tut01_SimulatingAnOrbit_py.xml | 25 +++
.../Tut02_SimpleOrbitTransfer.xml | 25 +++
...ut03_Target_FiniteBurn_To_Raise_Apogee.xml | 25 +++
.../Tut04_Mars_B_Plane_Targeting.xml | 25 +++
.idea/runConfigurations/example_py.xml | 25 +++
.idea/vcs.xml | 12 ++
README.md | 2 +
examples/scripts/example.script | 172 +++++++++---------
...Tut03_Target_FiniteBurn_To_Raise_Apogee.py | 14 +-
gmat_py_simple/burn.py | 26 ++-
gmat_py_simple/orbit.py | 22 +--
load_gmat.py | 2 +-
17 files changed, 345 insertions(+), 114 deletions(-)
create mode 100644 .idea/GMAT-Python-simple.iml
create mode 100644 .idea/inspectionProfiles/Project_Default.xml
create mode 100644 .idea/inspectionProfiles/profiles_settings.xml
create mode 100644 .idea/misc.xml
create mode 100644 .idea/runConfigurations/001_Creating_a_Spacecraft.xml
create mode 100644 .idea/runConfigurations/Tut01_SimulatingAnOrbit_py.xml
create mode 100644 .idea/runConfigurations/Tut02_SimpleOrbitTransfer.xml
create mode 100644 .idea/runConfigurations/Tut03_Target_FiniteBurn_To_Raise_Apogee.xml
create mode 100644 .idea/runConfigurations/Tut04_Mars_B_Plane_Targeting.xml
create mode 100644 .idea/runConfigurations/example_py.xml
create mode 100644 .idea/vcs.xml
diff --git a/.idea/GMAT-Python-simple.iml b/.idea/GMAT-Python-simple.iml
new file mode 100644
index 0000000..aad402c
--- /dev/null
+++ b/.idea/GMAT-Python-simple.iml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..8bc1bfb
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..1f2a26a
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/001_Creating_a_Spacecraft.xml b/.idea/runConfigurations/001_Creating_a_Spacecraft.xml
new file mode 100644
index 0000000..dc39c0d
--- /dev/null
+++ b/.idea/runConfigurations/001_Creating_a_Spacecraft.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/Tut01_SimulatingAnOrbit_py.xml b/.idea/runConfigurations/Tut01_SimulatingAnOrbit_py.xml
new file mode 100644
index 0000000..6ce2533
--- /dev/null
+++ b/.idea/runConfigurations/Tut01_SimulatingAnOrbit_py.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/Tut02_SimpleOrbitTransfer.xml b/.idea/runConfigurations/Tut02_SimpleOrbitTransfer.xml
new file mode 100644
index 0000000..828bd91
--- /dev/null
+++ b/.idea/runConfigurations/Tut02_SimpleOrbitTransfer.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/Tut03_Target_FiniteBurn_To_Raise_Apogee.xml b/.idea/runConfigurations/Tut03_Target_FiniteBurn_To_Raise_Apogee.xml
new file mode 100644
index 0000000..00730ba
--- /dev/null
+++ b/.idea/runConfigurations/Tut03_Target_FiniteBurn_To_Raise_Apogee.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/Tut04_Mars_B_Plane_Targeting.xml b/.idea/runConfigurations/Tut04_Mars_B_Plane_Targeting.xml
new file mode 100644
index 0000000..98cc924
--- /dev/null
+++ b/.idea/runConfigurations/Tut04_Mars_B_Plane_Targeting.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/example_py.xml b/.idea/runConfigurations/example_py.xml
new file mode 100644
index 0000000..86a7366
--- /dev/null
+++ b/.idea/runConfigurations/example_py.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..7ddfc9e
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index df24ffd..5ba30d3 100644
--- a/README.md
+++ b/README.md
@@ -6,6 +6,8 @@ Due to the wrapper's extensive use of classes and methods rather than strings, i
**This wrapper requires Python 3.10-3.12. It does not yet work with Python 3.13.**
+**On 19/4/25, NASA released [GMAT-R2025a](https://sourceforge.net/projects/gmat/). This wrapper was developed and tested with R2022a, so while I expect everything to still work, I cannot guarantee it. If you find any parts that don't work with R2025a, please raise an [issue](https://github.com/weasdown/GMAT-Python-simple/issues).**
+
## Examples
To demonstrate the wrapper, tutorials will be added to the [examples](https://github.com/weasdown/GMAT-Python-simple/tree/main/examples)/[tutorials](https://github.com/weasdown/GMAT-Python-simple/tree/main/examples/tutorials) directory as the required feature level is reached. These tutorials will match those distributed with GMAT by default (in the \[GMAT root]/samples folder) and will demonstrate the power of the wrapper to create missions using very little code.
diff --git a/examples/scripts/example.script b/examples/scripts/example.script
index 1d60ff0..5297922 100644
--- a/examples/scripts/example.script
+++ b/examples/scripts/example.script
@@ -1,5 +1,5 @@
%General Mission Analysis Tool(GMAT) Script
-%Created: 2024-01-19 14:31:25
+%Created: 2025-08-09 21:24:21
%----------------------------------------
@@ -7,109 +7,109 @@
%----------------------------------------
Create Spacecraft ExampleSat;
-GMAT ExampleSat.DateFormat = UTCGregorian;
-GMAT ExampleSat.Epoch = '01 Jan 2000 12:00:00.000';
-GMAT ExampleSat.CoordinateSystem = EarthMJ2000Eq;
-GMAT ExampleSat.DisplayStateType = Keplerian;
-GMAT ExampleSat.SMA = 83474.31799999907;
-GMAT ExampleSat.ECC = 0.8965199999999991;
-GMAT ExampleSat.INC = 12.4606;
-GMAT ExampleSat.RAAN = 292.8362;
-GMAT ExampleSat.AOP = 218.9805;
-GMAT ExampleSat.TA = 181.0000000000006;
-GMAT ExampleSat.DryMass = 850;
-GMAT ExampleSat.Cd = 2.2;
-GMAT ExampleSat.Cr = 1.8;
-GMAT ExampleSat.DragArea = 15;
-GMAT ExampleSat.SRPArea = 1;
-GMAT ExampleSat.SPADDragScaleFactor = 1;
-GMAT ExampleSat.SPADSRPScaleFactor = 1;
-GMAT ExampleSat.AtmosDensityScaleFactor = 1;
-GMAT ExampleSat.ExtendedMassPropertiesModel = 'None';
-GMAT ExampleSat.NAIFId = -10000001;
-GMAT ExampleSat.NAIFIdReferenceFrame = -9000001;
-GMAT ExampleSat.OrbitColor = Red;
-GMAT ExampleSat.TargetColor = Teal;
-GMAT ExampleSat.OrbitErrorCovariance = [ 1e+70 0 0 0 0 0 ; 0 1e+70 0 0 0 0 ; 0 0 1e+70 0 0 0 ; 0 0 0 1e+70 0 0 ; 0 0 0 0 1e+70 0 ; 0 0 0 0 0 1e+70 ];
-GMAT ExampleSat.CdSigma = 1e+70;
-GMAT ExampleSat.CrSigma = 1e+70;
-GMAT ExampleSat.Id = 'SatId';
-GMAT ExampleSat.Attitude = CoordinateSystemFixed;
-GMAT ExampleSat.SPADSRPInterpolationMethod = Bilinear;
-GMAT ExampleSat.SPADSRPScaleFactorSigma = 1e+70;
-GMAT ExampleSat.SPADDragInterpolationMethod = Bilinear;
-GMAT ExampleSat.SPADDragScaleFactorSigma = 1e+70;
-GMAT ExampleSat.AtmosDensityScaleFactorSigma = 1e+70;
-GMAT ExampleSat.ModelFile = 'aura.3ds';
-GMAT ExampleSat.ModelOffsetX = 0;
-GMAT ExampleSat.ModelOffsetY = 0;
-GMAT ExampleSat.ModelOffsetZ = 0;
-GMAT ExampleSat.ModelRotationX = 0;
-GMAT ExampleSat.ModelRotationY = 0;
-GMAT ExampleSat.ModelRotationZ = 0;
-GMAT ExampleSat.ModelScale = 1;
-GMAT ExampleSat.AttitudeDisplayStateType = 'Quaternion';
-GMAT ExampleSat.AttitudeRateDisplayStateType = 'AngularVelocity';
-GMAT ExampleSat.AttitudeCoordinateSystem = EarthMJ2000Eq;
-GMAT ExampleSat.EulerAngleSequence = '321';
+ExampleSat.DateFormat = UTCGregorian;
+ExampleSat.Epoch = '01 Jan 2000 12:00:00.000';
+ExampleSat.CoordinateSystem = EarthMJ2000Eq;
+ExampleSat.DisplayStateType = Keplerian;
+ExampleSat.SMA = 83474.31799999907;
+ExampleSat.ECC = 0.8965199999999991;
+ExampleSat.INC = 12.4606;
+ExampleSat.RAAN = 292.8362;
+ExampleSat.AOP = 218.9805;
+ExampleSat.TA = 181.0000000000006;
+ExampleSat.DryMass = 850;
+ExampleSat.Cd = 2.2;
+ExampleSat.Cr = 1.8;
+ExampleSat.DragArea = 15;
+ExampleSat.SRPArea = 1;
+ExampleSat.SPADDragScaleFactor = 1;
+ExampleSat.SPADSRPScaleFactor = 1;
+ExampleSat.AtmosDensityScaleFactor = 1;
+ExampleSat.ExtendedMassPropertiesModel = 'None';
+ExampleSat.NAIFId = -10000001;
+ExampleSat.NAIFIdReferenceFrame = -9000001;
+ExampleSat.OrbitColor = Red;
+ExampleSat.TargetColor = Teal;
+ExampleSat.OrbitErrorCovariance = [ 1e+70 0 0 0 0 0 ; 0 1e+70 0 0 0 0 ; 0 0 1e+70 0 0 0 ; 0 0 0 1e+70 0 0 ; 0 0 0 0 1e+70 0 ; 0 0 0 0 0 1e+70 ];
+ExampleSat.CdSigma = 1e+70;
+ExampleSat.CrSigma = 1e+70;
+ExampleSat.Id = 'SatId';
+ExampleSat.Attitude = CoordinateSystemFixed;
+ExampleSat.SPADSRPInterpolationMethod = Bilinear;
+ExampleSat.SPADSRPScaleFactorSigma = 1e+70;
+ExampleSat.SPADDragInterpolationMethod = Bilinear;
+ExampleSat.SPADDragScaleFactorSigma = 1e+70;
+ExampleSat.AtmosDensityScaleFactorSigma = 1e+70;
+ExampleSat.ModelFile = 'aura.3ds';
+ExampleSat.ModelOffsetX = 0;
+ExampleSat.ModelOffsetY = 0;
+ExampleSat.ModelOffsetZ = 0;
+ExampleSat.ModelRotationX = 0;
+ExampleSat.ModelRotationY = 0;
+ExampleSat.ModelRotationZ = 0;
+ExampleSat.ModelScale = 1;
+ExampleSat.AttitudeDisplayStateType = 'Quaternion';
+ExampleSat.AttitudeRateDisplayStateType = 'AngularVelocity';
+ExampleSat.AttitudeCoordinateSystem = EarthMJ2000Eq;
+ExampleSat.EulerAngleSequence = '321';
%----------------------------------------
%---------- ForceModels
%----------------------------------------
Create ForceModel LowEarthProp_ForceModel;
-GMAT LowEarthProp_ForceModel.CentralBody = Earth;
-GMAT LowEarthProp_ForceModel.PrimaryBodies = {Earth};
-GMAT LowEarthProp_ForceModel.PointMasses = {Luna, Sun};
-GMAT LowEarthProp_ForceModel.SRP = On;
-GMAT LowEarthProp_ForceModel.RelativisticCorrection = Off;
-GMAT LowEarthProp_ForceModel.ErrorControl = RSSStep;
-GMAT LowEarthProp_ForceModel.GravityField.Earth.Degree = 10;
-GMAT LowEarthProp_ForceModel.GravityField.Earth.Order = 10;
-GMAT LowEarthProp_ForceModel.GravityField.Earth.StmLimit = 100;
-GMAT LowEarthProp_ForceModel.GravityField.Earth.PotentialFile = 'JGM2.cof';
-GMAT LowEarthProp_ForceModel.GravityField.Earth.TideModel = 'None';
-GMAT LowEarthProp_ForceModel.SRP.Flux = 1367;
-GMAT LowEarthProp_ForceModel.SRP.SRPModel = Spherical;
-GMAT LowEarthProp_ForceModel.SRP.Nominal_Sun = 149597870.691;
-GMAT LowEarthProp_ForceModel.Drag.AtmosphereModel = JacchiaRoberts;
-GMAT LowEarthProp_ForceModel.Drag.HistoricWeatherSource = 'ConstantFluxAndGeoMag';
-GMAT LowEarthProp_ForceModel.Drag.PredictedWeatherSource = 'ConstantFluxAndGeoMag';
-GMAT LowEarthProp_ForceModel.Drag.CSSISpaceWeatherFile = 'SpaceWeather-All-v1.2.txt';
-GMAT LowEarthProp_ForceModel.Drag.SchattenFile = 'SchattenPredict.txt';
-GMAT LowEarthProp_ForceModel.Drag.F107 = 150;
-GMAT LowEarthProp_ForceModel.Drag.F107A = 150;
-GMAT LowEarthProp_ForceModel.Drag.MagneticIndex = 3;
-GMAT LowEarthProp_ForceModel.Drag.SchattenErrorModel = 'Nominal';
-GMAT LowEarthProp_ForceModel.Drag.SchattenTimingModel = 'NominalCycle';
-GMAT LowEarthProp_ForceModel.Drag.DragModel = 'Spherical';
+LowEarthProp_ForceModel.CentralBody = Earth;
+LowEarthProp_ForceModel.PrimaryBodies = {Earth};
+LowEarthProp_ForceModel.PointMasses = {Luna, Sun};
+LowEarthProp_ForceModel.SRP = On;
+LowEarthProp_ForceModel.RelativisticCorrection = Off;
+LowEarthProp_ForceModel.ErrorControl = RSSStep;
+LowEarthProp_ForceModel.GravityField.Earth.Degree = 10;
+LowEarthProp_ForceModel.GravityField.Earth.Order = 10;
+LowEarthProp_ForceModel.GravityField.Earth.StmLimit = 100;
+LowEarthProp_ForceModel.GravityField.Earth.PotentialFile = 'JGM2.cof';
+LowEarthProp_ForceModel.GravityField.Earth.TideModel = 'None';
+LowEarthProp_ForceModel.SRP.Flux = 1367;
+LowEarthProp_ForceModel.SRP.SRPModel = Spherical;
+LowEarthProp_ForceModel.SRP.Nominal_Sun = 149597870.691;
+LowEarthProp_ForceModel.Drag.AtmosphereModel = JacchiaRoberts;
+LowEarthProp_ForceModel.Drag.HistoricWeatherSource = 'ConstantFluxAndGeoMag';
+LowEarthProp_ForceModel.Drag.PredictedWeatherSource = 'ConstantFluxAndGeoMag';
+LowEarthProp_ForceModel.Drag.CSSISpaceWeatherFile = 'SpaceWeather-All-v1.2.txt';
+LowEarthProp_ForceModel.Drag.SchattenFile = 'SchattenPredict.txt';
+LowEarthProp_ForceModel.Drag.F107 = 150;
+LowEarthProp_ForceModel.Drag.F107A = 150;
+LowEarthProp_ForceModel.Drag.MagneticIndex = 3;
+LowEarthProp_ForceModel.Drag.SchattenErrorModel = 'Nominal';
+LowEarthProp_ForceModel.Drag.SchattenTimingModel = 'NominalCycle';
+LowEarthProp_ForceModel.Drag.DragModel = 'Spherical';
%----------------------------------------
%---------- Propagators
%----------------------------------------
Create Propagator LowEarthProp;
-GMAT LowEarthProp.FM = LowEarthProp_ForceModel;
-GMAT LowEarthProp.Type = RungeKutta89;
-GMAT LowEarthProp.InitialStepSize = 60;
-GMAT LowEarthProp.Accuracy = 9.999999999999999e-12;
-GMAT LowEarthProp.MinStep = 0.001;
-GMAT LowEarthProp.MaxStep = 2700;
-GMAT LowEarthProp.MaxStepAttempts = 50;
-GMAT LowEarthProp.StopIfAccuracyIsViolated = true;
+LowEarthProp.FM = LowEarthProp_ForceModel;
+LowEarthProp.Type = RungeKutta89;
+LowEarthProp.InitialStepSize = 60;
+LowEarthProp.Accuracy = 9.999999999999999e-12;
+LowEarthProp.MinStep = 0;
+LowEarthProp.MaxStep = 2700;
+LowEarthProp.MaxStepAttempts = 50;
+LowEarthProp.StopIfAccuracyIsViolated = true;
%----------------------------------------
%---------- Burns
%----------------------------------------
Create ImpulsiveBurn IB1;
-GMAT IB1.CoordinateSystem = EarthMJ2000Eq;
-GMAT IB1.Element1 = 0.2;
-GMAT IB1.Element2 = 0;
-GMAT IB1.Element3 = 0;
-GMAT IB1.DecrementMass = false;
-GMAT IB1.Isp = 300;
-GMAT IB1.GravitationalAccel = 9.81;
+IB1.CoordinateSystem = EarthMJ2000Eq;
+IB1.Element1 = 0.2;
+IB1.Element2 = 0;
+IB1.Element3 = 0;
+IB1.DecrementMass = false;
+IB1.Isp = 300;
+IB1.GravitationalAccel = 9.81;
%----------------------------------------
diff --git a/examples/tutorials/Tut03_Target_FiniteBurn_To_Raise_Apogee.py b/examples/tutorials/Tut03_Target_FiniteBurn_To_Raise_Apogee.py
index 2d6f034..967be91 100644
--- a/examples/tutorials/Tut03_Target_FiniteBurn_To_Raise_Apogee.py
+++ b/examples/tutorials/Tut03_Target_FiniteBurn_To_Raise_Apogee.py
@@ -7,15 +7,17 @@
import gmat_py_simple as gpy
import os
-log_path = os.path.normpath(f'{os.getcwd()}/examples/logs/GMAT-Tut03-Log.txt')
-gmat.UseLogFile(log_path)
-gmat.EchoLogFile(False) # set to True to view log output in console (e.g. live iteration results)
+# # Uncomment to enable logging
+# log_path = os.path.normpath(f'{os.getcwd()}/examples/logs/GMAT-Tut03-Log.txt')
+# gmat.UseLogFile(log_path)
+# gmat.EchoLogFile(False) # set to True to view log output in console (e.g. live iteration results)
sat_params = {
'Name': 'DefaultSC',
- 'Hardware': {'Tanks': {'chemical': [{'Name': 'ChemicalTank1'}], },
- 'Thrusters': {'chemical': [{'Name': 'ChemicalThruster1', 'Tanks': 'ChemicalTank1'}]},
- }
+ 'Hardware': {
+ 'ChemicalTanks': [{'Name': 'ChemicalTank1'}, ],
+ 'ChemicalThrusters': [{'Name': 'ChemicalThruster1', 'Tanks': 'ChemicalTank1'}, ],
+ }
}
sat = gpy.Spacecraft.from_dict(sat_params)
diff --git a/gmat_py_simple/burn.py b/gmat_py_simple/burn.py
index fd4d800..bbbff24 100644
--- a/gmat_py_simple/burn.py
+++ b/gmat_py_simple/burn.py
@@ -93,7 +93,8 @@ def EnableThrust(self):
class ImpulsiveBurn(Burn):
- def __init__(self, name, coord_sys: gpy.OrbitState.CoordinateSystem | dict | str = None, delta_v: list[int | float] = None,
+ def __init__(self, name, coord_sys: gpy.OrbitState.CoordinateSystem | dict | str = None,
+ delta_v: list[int | float] = None,
decrement_mass: bool = False, tanks: gpy.Tank | list[gpy.Tank] | str = None, isp: int | float = 300,
gravitational_accel: float = 9.81):
super().__init__('ImpulsiveBurn', name)
@@ -103,9 +104,9 @@ def __init__(self, name, coord_sys: gpy.OrbitState.CoordinateSystem | dict | str
# Get default coordinate system from GMAT object
self.coord_sys_name = self.GetStringParameter('CoordinateSystem')
- self.origin: str = self.GetStringParameter('Origin')
- self.axes: str = self.GetStringParameter('Axes')
- self.origin = self.GetStringParameter('Origin')
+ self.origin_name: str = self.GetStringParameter('Origin')
+ self.origin_body: gmat.Planet = None
+ self.axes_name: str = self.GetStringParameter('Axes')
# Update coordinate system if user has supplied one
if coord_sys is not None:
@@ -126,16 +127,22 @@ def __init__(self, name, coord_sys: gpy.OrbitState.CoordinateSystem | dict | str
self.SetStringParameter('Origin', dict_origin)
self.SetStringParameter('Axes', dict_axes)
- elif isinstance(coord_sys, gpy.OrbitState.CoordinateSystem | gmat.CoordinateSystem): # coord_sys is a wrapper or GMAT CoordinateSystem object
+ elif isinstance(coord_sys,
+ gpy.OrbitState.CoordinateSystem | gmat.CoordinateSystem): # coord_sys is a wrapper or GMAT CoordinateSystem object
coord_sys.Initialize()
+
+ # Below avoids false positive type hint warning in PyCharm 2025.2.
+ # noinspection PyTypeHints
coord_sys_new: gpy.OrbitState.CoordinateSystem | gmat.CoordinateSystem = coord_sys
self.coord_sys_name = coord_sys_new.GetName()
# Extract celestial body (e.g. Earth) and axes (e.g. MJ2000Eq) from CoordinateSystem
if isinstance(coord_sys_new, gpy.OrbitState.CoordinateSystem):
- self.origin: gmat.Planet = coord_sys_new.origin # obj for celestial body at coord sys origin
+ self.origin_body: gmat.Planet = coord_sys_new.origin # obj for celestial body at coord sys origin
+ self.origin_name: str = self.origin_body.GetName()
self.axes: gpy.OrbitState.CoordinateSystem.Axes = coord_sys_new.axes
self.axes_name: str = self.axes.name
+
elif isinstance(coord_sys_new, gmat.CoordinateSystem):
# coord_sys is of type gmat.CoordinateSystem
self.origin_name: str = coord_sys_new.GetField('Origin')
@@ -150,10 +157,11 @@ def __init__(self, name, coord_sys: gpy.OrbitState.CoordinateSystem | dict | str
# Attach CoordinateSystem's celestial body (Origin) to the ImpulsiveBurn
self.SetStringParameter(2, self.origin_name) # 1 for CS, 2 for Origin, 3 for Axes
- self.SetRefObject(self.origin, gmat.CELESTIAL_BODY, self.origin_name)
+ self.SetRefObject(self.origin_body, gmat.CELESTIAL_BODY, self.origin_name)
- # Attach CoordinateSystem's Axes to the ImpulsiveBurn
- self.SetStringParameter(3, self.axes_name) # 1 for CS, 2 for Origin, 3 for Axes
+ # Attach CoordinateSystem's Axes to the ImpulsiveBurn. param is 1 for CS, 2 for Origin, 3 for Axes
+ self.SetStringParameter(3, self.axes_name.replace('_', '').replace(self.origin_name,
+ ''))
else:
raise TypeError(f'CoordinateSystem type "{type(coord_sys).__name__}" not recognized in '
diff --git a/gmat_py_simple/orbit.py b/gmat_py_simple/orbit.py
index ae15c49..fd56e94 100644
--- a/gmat_py_simple/orbit.py
+++ b/gmat_py_simple/orbit.py
@@ -1,9 +1,7 @@
from __future__ import annotations
-import gmat_py_simple
from load_gmat import gmat
-import gmat_py_simple as gpy
from gmat_py_simple.basics import GmatObject
from gmat_py_simple.utils import *
@@ -264,7 +262,7 @@ class PrimaryBody:
# TODO: use fact that PrimaryBody is alias for GravityField - in init call GravityField.__init__
def __init__(self, fm: ForceModel, body: str = 'Earth',
gravity: ForceModel.GravityField = None,
- drag: ForceModel.DragForce | False = False):
+ drag: ForceModel.DragForce | bool = False):
self._force_model = fm
self._body = body if body else self._force_model.central_body
self._gravity = gravity if gravity else ForceModel.GravityField()
@@ -544,7 +542,8 @@ def __init__(self, name: str, origin: str = 'Earth', axes: str = 'MJ2000Eq', pri
secondary: str = None, xaxis: str = None, yaxis: str = None, zaxis: str = None, epoch: str = None,
alignment_vec_x: int = None, alignment_vec_y: int = None, alignment_vec_z: int = None,
constraint_vec_x: int = None, constraint_vec_y: int = None, constraint_vec_z: int = None,
- constraint_ref_vec_x: int = None, constraint_ref_vec_y: int = None, constraint_ref_vec_z: int = None,
+ constraint_ref_vec_x: int = None, constraint_ref_vec_y: int = None,
+ constraint_ref_vec_z: int = None,
constraint_coord_sys: str = None, ref_object: str = None
):
# TODO: remove kwargs if possible, if not document as another 2do
@@ -607,22 +606,21 @@ def __init__(self, name: str, origin: str = 'Earth', axes: str = 'MJ2000Eq', pri
raise AttributeError(f'Specified axes type "{axes}" is not recognized. Please specify one of the '
f'following:\n\t{self.allowed_values["Axes"]}')
else:
- self.axes: str = axes
- if self.axes in list(self.allowed_values['AxesTypeSpecific'].keys()):
- axes_specific_values = self.allowed_values['AxesTypeSpecific'][self.axes]
+ if axes in list(self.allowed_values['AxesTypeSpecific'].keys()):
+ axes_specific_values = self.allowed_values['AxesTypeSpecific'][axes]
# TODO set params/ref objs for all axes types
- if self.axes == 'ObjectReferenced':
+ if axes == 'ObjectReferenced':
self.primary = primary
self.secondary = secondary
self.xaxis = xaxis
self.yaxis = yaxis
self.zaxis = zaxis
- elif self.axes == 'TOE' or self.axes == 'MOE':
+ elif (axes == 'TOE') or (axes == 'MOE'):
self.epoch = epoch
- elif self.axes == 'LocalAlignedConstrained':
+ elif axes == 'LocalAlignedConstrained':
self.alignment_vec_x = alignment_vec_x
self.alignment_vec_y = alignment_vec_y
self.alignment_vec_z = alignment_vec_z
@@ -635,7 +633,7 @@ def __init__(self, name: str, origin: str = 'Earth', axes: str = 'MJ2000Eq', pri
self.constraint_coord_sys = constraint_coord_sys
self.ref_object = ref_object
- self.axes = OrbitState.CoordinateSystem.Axes(axes, f'{origin}_{axes}')
+ self.axes: OrbitState.CoordinateSystem.Axes = OrbitState.CoordinateSystem.Axes(axes, f'{origin}_{axes}')
self.SetRefObject(self.axes, gmat.AXIS_SYSTEM, self.axes.name)
# gpy.Initialize()
@@ -655,7 +653,7 @@ def from_sat(cls, sc: gpy.Spacecraft) -> OrbitState.CoordinateSystem:
sc_cs_gmat_obj = sc.gmat_obj.GetRefObject(150, name)
origin = sc_cs_gmat_obj.GetField('Origin')
axes = sc_cs_gmat_obj.GetField('Axes')
- coord_sys = cls(name=name, origin=origin, axes=axes, no_gmat_object=True)
+ coord_sys: OrbitState.CoordinateSystem = cls(name=name, origin=origin, axes=axes)
return coord_sys
@property
diff --git a/load_gmat.py b/load_gmat.py
index 571843a..27173da 100644
--- a/load_gmat.py
+++ b/load_gmat.py
@@ -9,7 +9,7 @@
from os import path
apistartup = "api_startup_file.txt"
-GmatInstall = "C:\\Users\\weasd\\Desktop\\GMAT\\gmat-win-R2022a\\GMAT"
+GmatInstall = "C:\\Users\\weasd\\OneDrive\\Desktop\\GMAT\\gmat-win-R2025a"
GmatBinPath = GmatInstall + "/bin"
Startup = GmatBinPath + "/" + apistartup
From af2d392ba14fb6110161d03361518a319bf1dbdb Mon Sep 17 00:00:00 2001
From: weasdown <34220924+weasdown@users.noreply.github.com>
Date: Fri, 15 Aug 2025 22:26:12 +0100
Subject: [PATCH 3/7] feat: add pyproject.toml
---
pyproject.toml | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
create mode 100644 pyproject.toml
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..6f67d03
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,23 @@
+[build-system]
+requires = ["hatchling >= 1.26"]
+build-backend = "hatchling.build"
+
+[project]
+name = "GMAT-Python-simple"
+version = "0.4.1"
+authors = [
+ { name="William Easdown Babb", email="weasdown99@gmail.com" },
+]
+description = "An extra wrapper for the GMAT Python API to simplify setting up mission simulations."
+readme = "README.md"
+requires-python = ">=3.9"
+classifiers = [
+ "Programming Language :: Python :: 3",
+ "Operating System :: OS Independent",
+]
+license = "MIT"
+license-files = ["LICEN[CS]E*"]
+
+[project.urls]
+Homepage = "https://github.com/weasdown/GMAT-Python-simple/"
+Issues = "https://github.com/weasdown/GMAT-Python-simple/issues/"
\ No newline at end of file
From 00d2bf69253b9b214435ed6dc2343a7d320add62 Mon Sep 17 00:00:00 2001
From: weasdown <34220924+weasdown@users.noreply.github.com>
Date: Sun, 17 Aug 2025 17:07:25 +0100
Subject: [PATCH 4/7] Squashed commit of the following:
commit 933c7ba5b0c118877c114661422ccfab18b59d8d
Author: weasdown <34220924+weasdown@users.noreply.github.com>
Date: Sun Aug 17 11:44:07 2025 +0100
docs: improve docstring for _gmat_path()
commit 56078c4451647c65a594b8eadc6caedac7f6f428
Author: weasdown <34220924+weasdown@users.noreply.github.com>
Date: Sun Aug 17 11:42:48 2025 +0100
style: remove prints
commit a2baffd2d70a0752bec35fc4dee23d39f21e4ba3
Author: weasdown <34220924+weasdown@users.noreply.github.com>
Date: Sun Aug 17 11:41:00 2025 +0100
feat: add IDE files
commit 613a465fc8390e1cdaf3e7e9b6d3d67193b8cd23
Author: weasdown <34220924+weasdown@users.noreply.github.com>
Date: Sun Aug 17 11:40:12 2025 +0100
fix: fix and tidy imports
commit 667c4482aca9c457d772aa3748a538c1491bd8ec
Author: weasdown <34220924+weasdown@users.noreply.github.com>
Date: Sun Aug 17 11:36:19 2025 +0100
style: auto-formatting
commit ddad61f51a001029f8e18705928f1953614b9fc6
Author: weasdown <34220924+weasdown@users.noreply.github.com>
Date: Sun Aug 17 11:35:42 2025 +0100
fix: fix imports
commit f71f1b4cc0842874794aa668868152e0ac912751
Author: weasdown <34220924+weasdown@users.noreply.github.com>
Date: Sun Aug 17 11:33:54 2025 +0100
feat: make gmat library accessible package-wide
commit fdd97f117257bc271b9ec0ca459d18c57dd4e1f3
Author: weasdown <34220924+weasdown@users.noreply.github.com>
Date: Sun Aug 17 11:33:26 2025 +0100
feat: import gmat library as variable
commit e9e22e2f445e7620b1a759f889700628cd36c6ea
Author: weasdown <34220924+weasdown@users.noreply.github.com>
Date: Sun Aug 17 11:22:49 2025 +0100
fix: add missing numpy dependency in pyproject.toml, update package version number
commit acfca9225647bf160c1366b9db3caa14a1dc8bbe
Author: weasdown <34220924+weasdown@users.noreply.github.com>
Date: Sun Aug 17 11:21:14 2025 +0100
fix: add missing pyproject.toml from branch 9-python-packaging
commit 0701d131a5ee6cf195d5edf5d63719b278edde00
Author: weasdown <34220924+weasdown@users.noreply.github.com>
Date: Sun Aug 17 11:18:30 2025 +0100
refactor: rename load_gmat.py outside package to load_gmat_OLD.py, pending removal
commit fed65b2137c05b0208d69cbc2cd93bb7bf06cd92
Author: weasdown <34220924+weasdown@users.noreply.github.com>
Date: Sun Aug 17 11:18:06 2025 +0100
style: auto-formatting
commit 997aa82d768f7f1ea09be70205310109edd5f9be
Author: weasdown <34220924+weasdown@users.noreply.github.com>
Date: Sun Aug 17 11:16:54 2025 +0100
refactor: import gmat from package load_gmat
commit bbe162146073688a688ce7f69e4e5ced1c10a195
Author: weasdown <34220924+weasdown@users.noreply.github.com>
Date: Sun Aug 17 11:10:55 2025 +0100
feat: add load_gmat.py inside package
commit 1b49b59702f4692794b6f03ec6c051631e559291
Author: weasdown <34220924+weasdown@users.noreply.github.com>
Date: Sun Aug 17 11:02:50 2025 +0100
docs: add TODO to remove commented code unrelated to branch issue
commit 1269ae7225425397cd81504d02dc62870136c8a6
Author: weasdown <34220924+weasdown@users.noreply.github.com>
Date: Sun Aug 17 10:55:15 2025 +0100
docs: add TODO to implement _gmat_path_from_config_file()
commit a221d6253fc95491b5281a0763050b7ba08a256a
Author: weasdown <34220924+weasdown@users.noreply.github.com>
Date: Sun Aug 17 10:45:08 2025 +0100
feat: run import_lib.py at import
commit 36565e6a96115ef1b277018f31542cd7ef4b185a
Author: weasdown <34220924+weasdown@users.noreply.github.com>
Date: Sun Aug 17 10:44:37 2025 +0100
feat: add import_lib.py
---
.idea/dictionaries/project.xml | 7 ++
.idea/inspectionProfiles/Project_Default.xml | 36 +++++-
.../inspectionProfiles/profiles_settings.xml | 3 +-
.idea/vcs.xml | 3 -
examples/example.py | 2 +-
examples/minimum_propagate_using_defaults.py | 3 +-
examples/tutorials/Tut01_SimulatingAnOrbit.py | 6 +-
.../tutorials/Tut02_SimpleOrbitTransfer.py | 22 ++--
gmat_py_simple/__init__.py | 7 ++
gmat_py_simple/api_funcs.py | 3 +-
gmat_py_simple/basics.py | 3 +-
gmat_py_simple/burn.py | 2 +-
gmat_py_simple/commands.py | 104 +++++++++---------
gmat_py_simple/executive.py | 12 +-
gmat_py_simple/hardware.py | 2 +-
gmat_py_simple/import_lib.py | 25 +++++
gmat_py_simple/interpreter.py | 4 +-
gmat_py_simple/load_gmat.py | 26 +++++
gmat_py_simple/orbit.py | 2 +-
gmat_py_simple/parameter.py | 3 +-
gmat_py_simple/solver.py | 1 -
gmat_py_simple/spacecraft.py | 9 +-
gmat_py_simple/utils.py | 2 +-
load_gmat.py => load_gmat_OLD.py | 0
pyproject.toml | 4 +-
25 files changed, 193 insertions(+), 98 deletions(-)
create mode 100644 .idea/dictionaries/project.xml
create mode 100644 gmat_py_simple/import_lib.py
create mode 100644 gmat_py_simple/load_gmat.py
rename load_gmat.py => load_gmat_OLD.py (100%)
diff --git a/.idea/dictionaries/project.xml b/.idea/dictionaries/project.xml
new file mode 100644
index 0000000..966c379
--- /dev/null
+++ b/.idea/dictionaries/project.xml
@@ -0,0 +1,7 @@
+
+
+
+ gmatpy
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index 8bc1bfb..a8498c3 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -1,23 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
index 105ce2d..49380d7 100644
--- a/.idea/inspectionProfiles/profiles_settings.xml
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -1,6 +1,7 @@
-
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 7ddfc9e..883037f 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -6,7 +6,4 @@
-
-
-
\ No newline at end of file
diff --git a/examples/example.py b/examples/example.py
index e23cd53..65e8621 100644
--- a/examples/example.py
+++ b/examples/example.py
@@ -3,8 +3,8 @@
from __future__ import annotations
import os
-from load_gmat import gmat
import gmat_py_simple as gpy
+from gmat_py_simple import gmat as gmat
# Set log and script options
log_path = os.path.normpath(f'{os.getcwd()}/GMAT-Log-example.txt')
diff --git a/examples/minimum_propagate_using_defaults.py b/examples/minimum_propagate_using_defaults.py
index 1cc1866..78ff1bd 100644
--- a/examples/minimum_propagate_using_defaults.py
+++ b/examples/minimum_propagate_using_defaults.py
@@ -8,7 +8,8 @@
# Set log and script options
log_path = os.path.normpath(f'{os.getcwd()}/GMAT-Log.txt')
gmat.UseLogFile(log_path)
-gmat.GmatGlobal.Instance().SetCommandEchoMode(True) # enables "CurrentCommand: [command generating string]" print out in log
+gmat.GmatGlobal.Instance().SetCommandEchoMode(
+ True) # enables "CurrentCommand: [command generating string]" print out in log
gmat.EchoLogFile(False) # set to True to have the log also print to the console as it's written
# Shortcuts for later
diff --git a/examples/tutorials/Tut01_SimulatingAnOrbit.py b/examples/tutorials/Tut01_SimulatingAnOrbit.py
index badb050..c8ac8e8 100644
--- a/examples/tutorials/Tut01_SimulatingAnOrbit.py
+++ b/examples/tutorials/Tut01_SimulatingAnOrbit.py
@@ -2,10 +2,12 @@
# Written by William Easdown Babb
from __future__ import annotations
-from load_gmat import gmat
-import gmat_py_simple as gpy
+
import os
+import gmat_py_simple as gpy
+from gmat_py_simple import gmat
+
log_path = os.path.normpath(f'{os.getcwd()}/GMAT-Log.txt')
gmat.UseLogFile(log_path)
echo_log = False
diff --git a/examples/tutorials/Tut02_SimpleOrbitTransfer.py b/examples/tutorials/Tut02_SimpleOrbitTransfer.py
index 952f6b0..67748ab 100644
--- a/examples/tutorials/Tut02_SimpleOrbitTransfer.py
+++ b/examples/tutorials/Tut02_SimpleOrbitTransfer.py
@@ -25,17 +25,17 @@
# Targeting sequence to adjust parameters of the two burns (TOI and GOI) to achieve desired final orbit
tg1 = gpy.Target('Hohmann Transfer', dc1, exit_mode='SaveAndContinue', command_sequence=[
- # Vary the velocity of the TOI burn to achieve an apoapsis with RMAG = 42165 km
- gpy.Vary('Vary TOI', dc1, f'{toi.name}.Element1'),
- gpy.Maneuver('Perform TOI', toi, sat),
- gpy.Propagate('Prop To Apoapsis', sat, prop, f'{sat.name}.Earth.Apoapsis'),
- gpy.Achieve('Achieve RMAG = 42165', dc1, f'{sat.name}.Earth.RMAG', 42164.169, 0.1),
-
- # Vary the velocity of the GOI burn to achieve an eccentricity of 0.005
- gpy.Vary('Vary GOI', dc1, f'{goi.name}.Element1', max_step=0.2),
- gpy.Maneuver('Perform GOI', goi, sat),
- gpy.Achieve('Achieve ECC = 0.005', dc1, f'{sat.name}.Earth.ECC', 0.005, 0.0001)
- ])
+ # Vary the velocity of the TOI burn to achieve an apoapsis with RMAG = 42165 km
+ gpy.Vary('Vary TOI', dc1, f'{toi.name}.Element1'),
+ gpy.Maneuver('Perform TOI', toi, sat),
+ gpy.Propagate('Prop To Apoapsis', sat, prop, f'{sat.name}.Earth.Apoapsis'),
+ gpy.Achieve('Achieve RMAG = 42165', dc1, f'{sat.name}.Earth.RMAG', 42164.169, 0.1),
+
+ # Vary the velocity of the GOI burn to achieve an eccentricity of 0.005
+ gpy.Vary('Vary GOI', dc1, f'{goi.name}.Element1', max_step=0.2),
+ gpy.Maneuver('Perform GOI', goi, sat),
+ gpy.Achieve('Achieve ECC = 0.005', dc1, f'{sat.name}.Earth.ECC', 0.005, 0.0001)
+])
# Mission Command Sequence
mcs = [
diff --git a/gmat_py_simple/__init__.py b/gmat_py_simple/__init__.py
index e5f1806..90ba41e 100644
--- a/gmat_py_simple/__init__.py
+++ b/gmat_py_simple/__init__.py
@@ -1,3 +1,10 @@
+from .import_lib import gmat_path
+
+from .load_gmat import *
+
+# GMAT's built-in library that interfaces to GMAT's source code.
+gmat: types.ModuleType = load_gmat.gmat
+
from .api_funcs import *
from .basics import *
from .burn import *
diff --git a/gmat_py_simple/api_funcs.py b/gmat_py_simple/api_funcs.py
index 5758f04..2ed1d05 100644
--- a/gmat_py_simple/api_funcs.py
+++ b/gmat_py_simple/api_funcs.py
@@ -1,11 +1,12 @@
from __future__ import annotations
-from load_gmat import gmat
+from gmat_py_simple import gmat
import gmat_py_simple as gpy
import os.path
+## TODO remove commented code
# def GetObject(name: str) -> gmat.GmatBase:
# try:
# obj: gmat.GmatBase = gmat.GetObject(name)
diff --git a/gmat_py_simple/basics.py b/gmat_py_simple/basics.py
index 7a4b839..2c80552 100644
--- a/gmat_py_simple/basics.py
+++ b/gmat_py_simple/basics.py
@@ -1,7 +1,8 @@
from __future__ import annotations
import gmat_py_simple as gpy
-from load_gmat import gmat
+# from gmat_py_simple import gmat
+from gmat_py_simple.load_gmat import gmat
from datetime import datetime
diff --git a/gmat_py_simple/burn.py b/gmat_py_simple/burn.py
index bbbff24..a95f64d 100644
--- a/gmat_py_simple/burn.py
+++ b/gmat_py_simple/burn.py
@@ -3,7 +3,7 @@
import gmat_py_simple as gpy
from gmat_py_simple.basics import GmatObject
-from load_gmat import gmat
+from gmat_py_simple import gmat
class Burn(GmatObject):
diff --git a/gmat_py_simple/commands.py b/gmat_py_simple/commands.py
index b799e26..7ee65de 100644
--- a/gmat_py_simple/commands.py
+++ b/gmat_py_simple/commands.py
@@ -1,7 +1,7 @@
from __future__ import annotations
from math import pi
-from load_gmat import gmat
+from gmat_py_simple import gmat
import gmat_py_simple as gpy
from gmat_py_simple.utils import *
@@ -211,54 +211,54 @@ def __init__(self, name: str, solver: gpy.DifferentialCorrector | gmat.Different
# # param_type is the final element of the self.variable string, e.g. Periapsis for Sat.Earth.Periapsis
# param_eles = self.variable.split('.')
# param_type = param_eles[-1]
- # new_param = gpy.Parameter(param_type, self.variable)
- # for ele in param_eles:
- # body = 'Earth'
- # cs = 'EarthMJ2000Eq'
- # if ele in gpy.CelestialBodies(): # a CelestialBody is given, so need to set it as a ref object
- # # TODO: test this
- # body = ele
- #
- # if ele in gpy.CoordSystems():
- # cs = ele
- #
- # pass
- # new_param.SetRefObjectName(gmat.SPACE_POINT, body)
- # new_param.SetRefObjectName(gmat.COORDINATE_SYSTEM, cs)
- # new_param.Help()
- # print(new_param.gmat_base.GetRefObjectTypeArray())
- # new_param.SetRefObjectName(gmat.CELESTIAL_BODY, ele)
-
- # if ele in gpy.CoordSystems(): # a CoordinateSystem is given, so need to set it as a ref object
- # # TODO remove (debugging only)
- # test_bddot = gmat.Construct('BdotT', 'TestBdotT')
- # test_bddot.SetRefObjectName(gmat.SPACECRAFT, 'MAVEN')
- # # test_bddot.SetReference(gmat.GetObject('MAVEN'))
- # # print(gpy.Moderator().gmat_obj.GetListOfFactoryItems(gmat.PARAMETER))
- # # test_bddot.RenameRefObject(gmat.COORDINATE_SYSTEM, 'EarthMJ2000Eq', ele)
- # test_bddot.SetRefObjectName(gmat.COORDINATE_SYSTEM, ele)
- # cs = gmat.GetObject(ele)
- # test_bddot.SetRefObject(cs, gmat.COORDINATE_SYSTEM, cs.GetName())
- #
- # # test_bddot.SetRefObjectName(gmat.SPACECRAFT, 'MAVEN')
- # test_bddot.SetRefObject(gmat.GetObject('MAVEN'), gmat.SPACECRAFT, 'MAVEN')
- #
- # test_bddot.SetSolarSystem(gmat.GetSolarSystem())
- # # gmat.Initialize()
- # mod = gpy.Moderator().gmat_obj
- # mod.SetParameterRefObject(test_bddot, 'BdotT', cs.GetName(), '', '', 1)
- # test_bddot.Help()
- # test_bddot.Initialize()
- #
- # new_param.SetRefObjectName(gmat.COORDINATE_SYSTEM, ele)
- # # new_param.SetStringParameter(new_param.GetParameterID('CoordinateSystem'), ele)
- # # new_param.SetRefObject(gmat.GetObject(ele), gmat.COORDINATE_SYSTEM)
- # new_param.Help()
- # pass
- #
- # for body in gpy.CelestialBodies():
- # if body in self.variable:
- # new_param.SetRefObject(gmat.Planet(body), gmat.COORDINATE_SYSTEM)
+ # new_param = gpy.Parameter(param_type, self.variable)
+ # for ele in param_eles:
+ # body = 'Earth'
+ # cs = 'EarthMJ2000Eq'
+ # if ele in gpy.CelestialBodies(): # a CelestialBody is given, so need to set it as a ref object
+ # # TODO: test this
+ # body = ele
+ #
+ # if ele in gpy.CoordSystems():
+ # cs = ele
+ #
+ # pass
+ # new_param.SetRefObjectName(gmat.SPACE_POINT, body)
+ # new_param.SetRefObjectName(gmat.COORDINATE_SYSTEM, cs)
+ # new_param.Help()
+ # print(new_param.gmat_base.GetRefObjectTypeArray())
+ # new_param.SetRefObjectName(gmat.CELESTIAL_BODY, ele)
+
+ # if ele in gpy.CoordSystems(): # a CoordinateSystem is given, so need to set it as a ref object
+ # # TODO remove (debugging only)
+ # test_bddot = gmat.Construct('BdotT', 'TestBdotT')
+ # test_bddot.SetRefObjectName(gmat.SPACECRAFT, 'MAVEN')
+ # # test_bddot.SetReference(gmat.GetObject('MAVEN'))
+ # # print(gpy.Moderator().gmat_obj.GetListOfFactoryItems(gmat.PARAMETER))
+ # # test_bddot.RenameRefObject(gmat.COORDINATE_SYSTEM, 'EarthMJ2000Eq', ele)
+ # test_bddot.SetRefObjectName(gmat.COORDINATE_SYSTEM, ele)
+ # cs = gmat.GetObject(ele)
+ # test_bddot.SetRefObject(cs, gmat.COORDINATE_SYSTEM, cs.GetName())
+ #
+ # # test_bddot.SetRefObjectName(gmat.SPACECRAFT, 'MAVEN')
+ # test_bddot.SetRefObject(gmat.GetObject('MAVEN'), gmat.SPACECRAFT, 'MAVEN')
+ #
+ # test_bddot.SetSolarSystem(gmat.GetSolarSystem())
+ # # gmat.Initialize()
+ # mod = gpy.Moderator().gmat_obj
+ # mod.SetParameterRefObject(test_bddot, 'BdotT', cs.GetName(), '', '', 1)
+ # test_bddot.Help()
+ # test_bddot.Initialize()
+ #
+ # new_param.SetRefObjectName(gmat.COORDINATE_SYSTEM, ele)
+ # # new_param.SetStringParameter(new_param.GetParameterID('CoordinateSystem'), ele)
+ # # new_param.SetRefObject(gmat.GetObject(ele), gmat.COORDINATE_SYSTEM)
+ # new_param.Help()
+ # pass
+ #
+ # for body in gpy.CelestialBodies():
+ # if body in self.variable:
+ # new_param.SetRefObject(gmat.Planet(body), gmat.COORDINATE_SYSTEM)
self.value = value
self.SetStringParameter('GoalValue', str(self.value))
@@ -280,7 +280,8 @@ def SetRefObject(self, obj, type_int: int, obj_name: str = '') -> bool:
class BeginFiniteBurn(GmatCommand):
- def __init__(self, burn: gpy.FiniteBurn | gmat.FiniteBurn, spacecraft: gpy.Spacecraft | gmat.Spacecraft, name: str = ''):
+ def __init__(self, burn: gpy.FiniteBurn | gmat.FiniteBurn, spacecraft: gpy.Spacecraft | gmat.Spacecraft,
+ name: str = ''):
super().__init__('BeginFiniteBurn', name)
# Assign the user-provided FiniteBurn to this command
@@ -293,7 +294,8 @@ def __init__(self, burn: gpy.FiniteBurn | gmat.FiniteBurn, spacecraft: gpy.Space
# self.spacecraft.Help()
# print(type(self.spacecraft))
# self.burn.SetSpacecraftToManeuver(gpy.extract_gmat_obj(self.spacecraft)) # update FiniteBurn's associated Spacecraft
- gpy.FiniteBurn.SetSpacecraftToManeuver(self.burn, gpy.extract_gmat_obj(self.spacecraft)) # update FiniteBurn's associated Spacecraft
+ gpy.FiniteBurn.SetSpacecraftToManeuver(self.burn, gpy.extract_gmat_obj(
+ self.spacecraft)) # update FiniteBurn's associated Spacecraft
self.Initialize()
diff --git a/gmat_py_simple/executive.py b/gmat_py_simple/executive.py
index 5d27e34..b144361 100644
--- a/gmat_py_simple/executive.py
+++ b/gmat_py_simple/executive.py
@@ -1,13 +1,10 @@
from __future__ import annotations
import gmat_py_simple as gpy
-from load_gmat import gmat
-from gmat_py_simple import GmatCommand
+from gmat_py_simple import gmat
-import sys
-
-def RunMission(mcs: list[GmatCommand]) -> int:
+def RunMission(mcs: list[gpy.GmatCommand]) -> int:
# Shortcut for running missions
return gpy.Moderator().RunMission(mcs)
@@ -199,13 +196,13 @@ def GetFirstCommand(self):
def Initialize(self):
self.gmat_obj.Initialize()
- def InsertCommand(self, command_to_insert: GmatCommand, preceding_command: GmatCommand):
+ def InsertCommand(self, command_to_insert: gpy.GmatCommand, preceding_command: gpy.GmatCommand):
return self.gmat_obj.InsertCommand(command_to_insert, preceding_command)
def RemoveObject(self, obj_type: int, name: str, del_only_if_not_used: bool = True) -> bool:
return self.gmat_obj.RemoveObject(obj_type, name, del_only_if_not_used)
- def RunMission(self, mission_command_sequence: list[GmatCommand]) -> int:
+ def RunMission(self, mission_command_sequence: list[gpy.GmatCommand]) -> int:
"""
Run the mission command sequence
@@ -214,6 +211,7 @@ def RunMission(self, mission_command_sequence: list[GmatCommand]) -> int:
:param mission_command_sequence:
:return:
"""
+
def update_command_objs_post_run(command_sequence: list[gpy.GmatCommand | gmat.GmatCommand]):
propagate_commands: list[gpy.Propagate] = [] # start a list of Propagates so their sats can be updated
target_commands: list[gpy.Target] = [] # start a list of Targets for checking convergence
diff --git a/gmat_py_simple/hardware.py b/gmat_py_simple/hardware.py
index f431f99..e3bfc73 100644
--- a/gmat_py_simple/hardware.py
+++ b/gmat_py_simple/hardware.py
@@ -5,7 +5,7 @@
import numpy as np
-from load_gmat import gmat
+from gmat_py_simple import gmat
import gmat_py_simple as gpy
from gmat_py_simple import GmatObject
diff --git a/gmat_py_simple/import_lib.py b/gmat_py_simple/import_lib.py
new file mode 100644
index 0000000..6df288c
--- /dev/null
+++ b/gmat_py_simple/import_lib.py
@@ -0,0 +1,25 @@
+import os
+
+
+def _gmat_path(from_env: bool = True) -> str:
+ """Import GMAT's built-in gmat library."""
+ return _gmat_path_from_env() if from_env else _gmat_path_from_config_file()
+
+
+def _gmat_path_from_env() -> str:
+ """Gets the path to the GMAT directory from the "GMAT" environment variable."""
+ try:
+ gmat_env: str = os.environ['GMAT']
+ except KeyError:
+ raise ValueError('"GMAT" environment variable not set.')
+
+ return gmat_env
+
+
+def _gmat_path_from_config_file() -> str:
+ """Gets the path to the GMAT directory from a configuration file."""
+ # TODO implement _gmat_path_from_config_file()
+ raise NotImplementedError
+
+
+gmat_path: str = _gmat_path()
diff --git a/gmat_py_simple/interpreter.py b/gmat_py_simple/interpreter.py
index 82f67c4..f38b38c 100644
--- a/gmat_py_simple/interpreter.py
+++ b/gmat_py_simple/interpreter.py
@@ -1,7 +1,8 @@
from __future__ import annotations
import gmat_py_simple as gpy
-from load_gmat import gmat
+
+from gmat_py_simple import gmat
class Validator:
@@ -31,4 +32,3 @@ def SetSolarSystem(self, ss: gmat.SolarSystem = gmat.GetSolarSystem()) -> bool:
def ValidateCommand(self, command: gpy.GmatCommand | gmat.GmatCommand):
return gpy.extract_gmat_obj(self).ValidateCommand(gpy.extract_gmat_obj(command))
-
diff --git a/gmat_py_simple/load_gmat.py b/gmat_py_simple/load_gmat.py
new file mode 100644
index 0000000..a028ec4
--- /dev/null
+++ b/gmat_py_simple/load_gmat.py
@@ -0,0 +1,26 @@
+import errno
+import os
+import sys
+import types
+
+from gmat_py_simple.import_lib import gmat_path
+
+api_startup = "api_startup_file.txt"
+gmat_bin_path = gmat_path + "/bin"
+startup = gmat_bin_path + "/" + api_startup
+
+if os.path.exists(startup):
+ print(f'Running GMAT in {gmat_path}')
+
+ sys.path.insert(1, gmat_bin_path)
+
+ gmat: types.ModuleType = __import__('gmatpy')
+
+ gmat.Setup(startup)
+
+else:
+ message: str = ("Please set up a GMAT startup file named " + api_startup +
+ " in the " + gmat_bin_path + " folder.")
+
+ raise FileNotFoundError(
+ errno.ENOENT, message, startup)
diff --git a/gmat_py_simple/orbit.py b/gmat_py_simple/orbit.py
index fd56e94..0158a9d 100644
--- a/gmat_py_simple/orbit.py
+++ b/gmat_py_simple/orbit.py
@@ -1,6 +1,6 @@
from __future__ import annotations
-from load_gmat import gmat
+from gmat_py_simple import gmat
from gmat_py_simple.basics import GmatObject
from gmat_py_simple.utils import *
diff --git a/gmat_py_simple/parameter.py b/gmat_py_simple/parameter.py
index 701026d..69fa16c 100644
--- a/gmat_py_simple/parameter.py
+++ b/gmat_py_simple/parameter.py
@@ -1,7 +1,8 @@
from __future__ import annotations
import gmat_py_simple as gpy
-from load_gmat import gmat
+
+from gmat_py_simple import gmat
# def CreateParameter(param_type: str, name: str) -> Parameter:
diff --git a/gmat_py_simple/solver.py b/gmat_py_simple/solver.py
index bf74718..9028f08 100644
--- a/gmat_py_simple/solver.py
+++ b/gmat_py_simple/solver.py
@@ -1,6 +1,5 @@
from __future__ import annotations
-from load_gmat import gmat
import gmat_py_simple as gpy
diff --git a/gmat_py_simple/spacecraft.py b/gmat_py_simple/spacecraft.py
index 9fc20d8..08cf3ca 100644
--- a/gmat_py_simple/spacecraft.py
+++ b/gmat_py_simple/spacecraft.py
@@ -1,7 +1,7 @@
from __future__ import annotations
import gmat_py_simple as gpy
-from load_gmat import gmat
+from gmat_py_simple import gmat
from gmat_py_simple.basics import GmatObject
from gmat_py_simple.orbit import OrbitState
@@ -585,7 +585,8 @@ def from_dict(cls, ep_tank_dict: dict) -> gpy.ElectricTank | None:
class Thruster(GmatObject):
def __init__(self, fuel_type: str, name: str, tanks: str | gpy.Tank | gmat.Tank | list[gpy.Tank] |
- list[gmat.FuelTank], mix_ratio: int | float | list[int | float] = None):
+ list[gmat.FuelTank],
+ mix_ratio: int | float | list[int | float] = None):
self.fuel_type = fuel_type
self.thruster_type = f'{self.fuel_type}Thruster' # 'ChemicalThruster' or 'ElectricThruster'
super().__init__(self.thruster_type, name)
@@ -673,7 +674,7 @@ def decrement_mass(self, true_false: bool):
class ChemicalThruster(Thruster):
def __init__(self, name: str, tanks: str | gpy.ChemicalTank | gmat.ChemicalTank |
- list[gpy.ChemicalTank] | list[gmat.ChemicalTank]):
+ list[gpy.ChemicalTank] | list[gmat.ChemicalTank]):
super().__init__('Chemical', name, tanks)
self.Validate()
@@ -691,7 +692,7 @@ def from_dict(cls, cp_thr_dict: dict) -> gpy.ChemicalThruster | None:
class ElectricThruster(Thruster):
def __init__(self, name: str, tanks: str | gpy.ElectricTank | gmat.ElectricTank |
- list[gpy.ElectricTank] | list[gmat.ElectricTank]):
+ list[gpy.ElectricTank] | list[gmat.ElectricTank]):
super().__init__('Electric', name, tanks)
self.Initialize()
diff --git a/gmat_py_simple/utils.py b/gmat_py_simple/utils.py
index a892150..ef5ff59 100644
--- a/gmat_py_simple/utils.py
+++ b/gmat_py_simple/utils.py
@@ -1,7 +1,7 @@
from __future__ import annotations
import gmat_py_simple as gpy
-from load_gmat import gmat
+from gmat_py_simple import gmat
import sys
from io import StringIO
diff --git a/load_gmat.py b/load_gmat_OLD.py
similarity index 100%
rename from load_gmat.py
rename to load_gmat_OLD.py
diff --git a/pyproject.toml b/pyproject.toml
index 6f67d03..bdb832e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,10 +1,10 @@
[build-system]
-requires = ["hatchling >= 1.26"]
+requires = ["hatchling >= 1.26", "numpy >= 2.0.0"]
build-backend = "hatchling.build"
[project]
name = "GMAT-Python-simple"
-version = "0.4.1"
+version = "0.4.3"
authors = [
{ name="William Easdown Babb", email="weasdown99@gmail.com" },
]
From 565694a71368c59ab93af284a252fa8e5f981ffc Mon Sep 17 00:00:00 2001
From: weasdown <34220924+weasdown@users.noreply.github.com>
Date: Sun, 17 Aug 2025 17:12:05 +0100
Subject: [PATCH 5/7] Set GMAT path (#18)
* feat: add import_lib.py
* feat: run import_lib.py at import
* docs: add TODO to implement _gmat_path_from_config_file()
* docs: add TODO to remove commented code unrelated to branch issue
* feat: add load_gmat.py inside package
* refactor: import gmat from package load_gmat
* style: auto-formatting
* refactor: rename load_gmat.py outside package to load_gmat_OLD.py, pending removal
* fix: add missing pyproject.toml from branch 9-python-packaging
* fix: add missing numpy dependency in pyproject.toml, update package version number
* feat: import gmat library as variable
* feat: make gmat library accessible package-wide
* fix: fix imports
* style: auto-formatting
* fix: fix and tidy imports
* feat: add IDE files
* style: remove prints
* docs: improve docstring for _gmat_path()
---
.idea/inspectionProfiles/Project_Default.xml | 27 ++++++--------------
.idea/vcs.xml | 3 +++
2 files changed, 11 insertions(+), 19 deletions(-)
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index a8498c3..26d0ee5 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -1,17 +1,6 @@
-
-
-
-
-
-
-
-
-
-
-
@@ -28,14 +17,14 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 883037f..4c6280e 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -6,4 +6,7 @@
+
+
+
\ No newline at end of file
From 714beddefda9100d13ea0ce8355ac37261562c4e Mon Sep 17 00:00:00 2001
From: weasdown <34220924+weasdown@users.noreply.github.com>
Date: Sun, 17 Aug 2025 17:15:58 +0100
Subject: [PATCH 6/7] chore: updates to .idea files
---
.idea/GMAT-Python-simple.iml | 3 ---
.idea/inspectionProfiles/profiles_settings.xml | 1 -
2 files changed, 4 deletions(-)
diff --git a/.idea/GMAT-Python-simple.iml b/.idea/GMAT-Python-simple.iml
index aad402c..ec63674 100644
--- a/.idea/GMAT-Python-simple.iml
+++ b/.idea/GMAT-Python-simple.iml
@@ -4,7 +4,4 @@
-
-
-
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
index 49380d7..cfcfda2 100644
--- a/.idea/inspectionProfiles/profiles_settings.xml
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -1,7 +1,6 @@
-
\ No newline at end of file
From e87b0eead3cc7ebe511aae56ba66a026686ecb78 Mon Sep 17 00:00:00 2001
From: weasdown <34220924+weasdown@users.noreply.github.com>
Date: Sun, 17 Aug 2025 17:25:10 +0100
Subject: [PATCH 7/7] feat: add getting GMAT path from config file
---
.../inspectionProfiles/profiles_settings.xml | 1 +
gmat_py_simple/import_lib.py | 23 +++++++++++++++----
2 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
index cfcfda2..dd4c951 100644
--- a/.idea/inspectionProfiles/profiles_settings.xml
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -1,6 +1,7 @@
+
\ No newline at end of file
diff --git a/gmat_py_simple/import_lib.py b/gmat_py_simple/import_lib.py
index 6df288c..313c421 100644
--- a/gmat_py_simple/import_lib.py
+++ b/gmat_py_simple/import_lib.py
@@ -1,15 +1,25 @@
import os
-def _gmat_path(from_env: bool = True) -> str:
+def _gmat_path() -> str:
"""Import GMAT's built-in gmat library."""
- return _gmat_path_from_env() if from_env else _gmat_path_from_config_file()
+ gmat_directory: str
+ try:
+ gmat_directory = _gmat_path_from_env()
+ except ValueError:
+ try:
+ gmat_directory = _gmat_path_from_config_file()
+ except FileNotFoundError:
+ raise
+
+ return gmat_directory
def _gmat_path_from_env() -> str:
"""Gets the path to the GMAT directory from the "GMAT" environment variable."""
try:
gmat_env: str = os.environ['GMAT']
+
except KeyError:
raise ValueError('"GMAT" environment variable not set.')
@@ -18,8 +28,13 @@ def _gmat_path_from_env() -> str:
def _gmat_path_from_config_file() -> str:
"""Gets the path to the GMAT directory from a configuration file."""
- # TODO implement _gmat_path_from_config_file()
- raise NotImplementedError
+
+ config_file = 'gmat_path.txt'
+
+ with open(config_file, 'r') as f:
+ gmat_directory: str = f.readline()
+
+ return gmat_directory
gmat_path: str = _gmat_path()