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 + + + external_reactions/rocket/x + + + + + + velocities/eci-y-fps + velocities/eci-velocity-mag-fps + + + external_reactions/rocket/y + + + + + + velocities/eci-z-fps + velocities/eci-velocity-mag-fps + + + external_reactions/rocket/z + + + + + 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])