From ae4652a268d0475dbf93d47a32ab7ddf4120aaef Mon Sep 17 00:00:00 2001
From: "Jon S. Berndt" <34601451+jonsberndt@users.noreply.github.com>
Date: Sun, 24 Sep 2023 04:32:41 -0600
Subject: [PATCH] Adding capability to aim external forces in inertial frame
(#962)
---
aircraft/ball/ball.xml | 67 +++++++++++++++--
aircraft/ball/iss_orbit.xml | 29 ++++++++
scripts/ball_orbit_phase.xml | 120 ++++++++++++++++++++++++++++++
src/models/FGExternalForce.cpp | 5 ++
src/models/FGExternalForce.h | 1 +
src/models/propulsion/FGForce.cpp | 2 +
src/models/propulsion/FGForce.h | 2 +-
tests/TestExternalReactions.py | 17 ++++-
8 files changed, 231 insertions(+), 12 deletions(-)
create mode 100644 aircraft/ball/iss_orbit.xml
create mode 100644 scripts/ball_orbit_phase.xml
diff --git a/aircraft/ball/ball.xml b/aircraft/ball/ball.xml
index f555528b8b..c265d73b6e 100644
--- a/aircraft/ball/ball.xml
+++ b/aircraft/ball/ball.xml
@@ -55,7 +55,7 @@
-0
-0
-0
- 40
+ 20000
0
0
@@ -100,14 +100,15 @@
fcs/parachute_reef_pos_norm
-
+ propulsion/rocket_thrust
+
aero/qbar-psf
fcs/parachute_reef_pos_norm
1.0
- 20.0
+ 10000.0
- -1
+ -1
+ 0
+ 0
+
+
+
+
+
+ propulsion/rocket_thrust
+
+
+ 0
0
0
-
+
+
+
-
+
+
+
+
+
+
+
+ velocities/eci-x-fps
+ velocities/eci-velocity-mag-fps
+
+
+
+
+
+
+
+
+ velocities/eci-y-fps
+ velocities/eci-velocity-mag-fps
+
+
+
+
+
+
+
+
+ velocities/eci-z-fps
+ velocities/eci-velocity-mag-fps
+
+
+
+
+
+
+
+
diff --git a/aircraft/ball/iss_orbit.xml b/aircraft/ball/iss_orbit.xml
new file mode 100644
index 0000000000..d88a549c64
--- /dev/null
+++ b/aircraft/ball/iss_orbit.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+ -4084.03
+ -5429.69
+ -0.5567
+
+
+
+ 90.0
+
+
+
+ 3.813252
+ -2.858118
+ 6.003066
+
+
+
+ 0.0
+ 0.0
+
+
+
diff --git a/scripts/ball_orbit_phase.xml b/scripts/ball_orbit_phase.xml
new file mode 100644
index 0000000000..3483b043c6
--- /dev/null
+++ b/scripts/ball_orbit_phase.xml
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+ Integrators
+
+ 0: No integrator (Freeze)
+ 1: Rectangular Euler
+ 2: Trapezoidal
+ 3: Adams Bashforth 2
+ 4: Adams Bashforth 3
+ 5: Adams Bashforth 4
+
+
+ simulation/integrator/rate/rotational
+ simulation/integrator/rate/translational
+ simulation/integrator/position/rotational
+ simulation/integrator/position/translational
+ simulation/gravity-model
+ simulation/output[0]/log_rate_hz
+
+ simulation/notify-time-trigger
+
+
+ Output message at 10 minute intervals
+
+ position/h-agl-ft
+ position/geod-alt-ft
+ position/lat-geod-deg
+ position/radius-to-vehicle-ft
+ velocities/eci-velocity-mag-fps
+ velocities/u-fps
+ simulation/frame
+ atmosphere/rho-slugs_ft3
+ orbital/specific-angular-momentum-ft2_sec
+ orbital/inclination-deg
+ orbital/right-ascension-deg
+ orbital/argument-of-perigee-deg
+ orbital/period-sec
+ orbital/eccentricity
+ orbital/apoapsis-radius-ft
+ orbital/periapsis-radius-ft
+ orbital/true-anomaly-deg
+
+ simulation/sim-time-sec >= simulation/notify-time-trigger
+
+
+
+
+ Lower perigee
+
+ simulation/sim-time-sec gt 10
+
+
+
+ simulation/sim-time-sec
+
+
+
+
+ Stop lowering perigee
+
+ simulation/sim-time-sec gt 12
+
+
+
+ simulation/sim-time-sec
+
+
+
+
+ Lower orbit below station (Thrust is in negative direction here)
+
+ simulation/sim-time-sec gt 2803
+
+
+
+ simulation/sim-time-sec
+
+
+
+
+ Stop lowering orbit below station
+
+ simulation/sim-time-sec gt 2808
+
+
+
+ simulation/sim-time-sec
+
+
+
+
+ Circularize orbit below station (Thrust is in negative direction here)
+
+ simulation/sim-time-sec gt 5591
+
+
+
+ simulation/sim-time-sec
+
+
+
+
+ Stop circularizing orbit below station
+
+ simulation/sim-time-sec gt 5598
+
+
+
+ simulation/sim-time-sec
+
+
+
+
+
diff --git a/src/models/FGExternalForce.cpp b/src/models/FGExternalForce.cpp
index 6c938d5f1c..a259f758b3 100644
--- a/src/models/FGExternalForce.cpp
+++ b/src/models/FGExternalForce.cpp
@@ -103,6 +103,8 @@ FGParameter* FGExternalForce::bind(Element *el, const string& magName,
ttype = tLocalBody;
} else if (sFrame == "WIND") {
ttype = tWindBody;
+ } else if (sFrame == "INERTIAL") {
+ ttype = tInertialBody;
} else {
cerr << el->ReadFrom()
<< "Invalid frame specified for external " << el->GetName() << ", \""
@@ -239,6 +241,9 @@ void FGExternalForce::Debug(int from)
case tWindBody:
cout << "WIND";
break;
+ case tInertialBody:
+ cout << "INERTIAL";
+ break;
default:
cout << "ERROR/UNKNOWN";
}
diff --git a/src/models/FGExternalForce.h b/src/models/FGExternalForce.h
index 5b1252a207..c231b6b7a1 100644
--- a/src/models/FGExternalForce.h
+++ b/src/models/FGExternalForce.h
@@ -111,6 +111,7 @@ CLASS DOCUMENTATION
completes the right handed system. This is modified from a normal
wind frame definition, which is rotated about the Y axis 180 degrees
from this WIND frame.
+ - INERTIAL frame refers to the ECI frame.
Much of the substance of this class is located in the FGForce base class,
from which this class is derived.
diff --git a/src/models/propulsion/FGForce.cpp b/src/models/propulsion/FGForce.cpp
index 33e2f5e701..f7f82d09cd 100644
--- a/src/models/propulsion/FGForce.cpp
+++ b/src/models/propulsion/FGForce.cpp
@@ -101,6 +101,8 @@ const FGMatrix33& FGForce::Transform(void) const
return fdmex->GetAuxiliary()->GetTw2b();
case tLocalBody:
return fdmex->GetPropagate()->GetTl2b();
+ case tInertialBody:
+ return fdmex->GetPropagate()->GetTi2b();
case tCustom:
case tNone:
return mT;
diff --git a/src/models/propulsion/FGForce.h b/src/models/propulsion/FGForce.h
index e6458d2e7b..84e3bc7543 100644
--- a/src/models/propulsion/FGForce.h
+++ b/src/models/propulsion/FGForce.h
@@ -227,7 +227,7 @@ class JSBSIM_API FGForce : public FGJSBBase
/// Destructor
virtual ~FGForce();
- enum TransformType { tNone, tWindBody, tLocalBody, tCustom };
+ enum TransformType { tNone, tWindBody, tLocalBody, tInertialBody, tCustom };
virtual const FGColumnVector3& GetBodyForces(void);
diff --git a/tests/TestExternalReactions.py b/tests/TestExternalReactions.py
index 316f004056..8f335c5238 100644
--- a/tests/TestExternalReactions.py
+++ b/tests/TestExternalReactions.py
@@ -23,6 +23,12 @@
from JSBSim_utils import JSBSimTestCase, CreateFDM, RunTest, CopyAircraftDef
+def getParachuteArea(tree):
+ parachute_area = 1.0
+ for value in tree.getroot().findall('external_reactions/force/function/product/value'):
+ parachute_area *= float(value.text)
+ return parachute_area
+
class TestExternalReactions(JSBSimTestCase):
def getLeverArm(self, fdm, name):
lax = (fdm['external_reactions/'+name+'/location-x-in']
@@ -52,9 +58,12 @@ def test_wind_frame(self):
self.assertAlmostEqual(fdm['external_reactions/parachute/y'], 0.0)
self.assertAlmostEqual(fdm['external_reactions/parachute/z'], 0.0)
+ tree, _, _ = CopyAircraftDef(script_path, self.sandbox)
+ parachute_area = getParachuteArea(tree)
+
while fdm.run():
Tw2b = fdm.get_auxiliary().get_Tw2b()
- mag = fdm['aero/qbar-psf'] * fdm['fcs/parachute_reef_pos_norm']*20.0
+ mag = fdm['aero/qbar-psf'] * fdm['fcs/parachute_reef_pos_norm']*parachute_area
f = Tw2b * np.mat([-1.0, 0.0, 0.0]).T * mag
self.assertAlmostEqual(fdm['forces/fbx-external-lbs'], f[0, 0])
self.assertAlmostEqual(fdm['forces/fby-external-lbs'], f[1, 0])
@@ -199,8 +208,7 @@ def test_body_frame(self):
def test_moment(self):
script_path = self.sandbox.path_to_jsbsim_file('scripts',
'ball_chute.xml')
- tree, aircraft_name, _ = CopyAircraftDef(script_path,
- self.sandbox)
+ tree, aircraft_name, _ = CopyAircraftDef(script_path, self.sandbox)
extReact_element = tree.getroot().find('external_reactions')
moment_element = et.SubElement(extReact_element, 'moment')
moment_element.attrib['name'] = 'parachute'
@@ -228,10 +236,11 @@ def test_moment(self):
self.assertAlmostEqual(fdm['external_reactions/parachute/n'], mDir[2])
fdm['external_reactions/parachute/magnitude-lbsft'] = -3.5
+ parachute_area = getParachuteArea(tree)
while fdm.run():
Tw2b = fdm.get_auxiliary().get_Tw2b()
- mag = fdm['aero/qbar-psf'] * fdm['fcs/parachute_reef_pos_norm']*20.0
+ mag = fdm['aero/qbar-psf'] * fdm['fcs/parachute_reef_pos_norm']*parachute_area
f = Tw2b * np.mat([-1.0, 0.0, 0.0]).T * mag
self.assertAlmostEqual(fdm['forces/fbx-external-lbs'], f[0, 0])
self.assertAlmostEqual(fdm['forces/fby-external-lbs'], f[1, 0])